diff -Nru openjdk-13-13~17/debian/changelog openjdk-13-13~18/debian/changelog --- openjdk-13-13~17/debian/changelog 2019-04-19 01:00:51.000000000 +0000 +++ openjdk-13-13~18/debian/changelog 2019-04-25 08:56:56.000000000 +0000 @@ -1,3 +1,16 @@ +openjdk-13 (13~18-1) experimental; urgency=medium + + * OpenJDK 13 snapshot, build 18. + * Add breaks to the openjdk-13-jre-headless package: + - For unattended upgrades: jetty9, netbeans, tomcat8, visualvm. + - For eclipse 3.8 removal: eclipse-platform. Addresses: #925071. + - For configuration with vendor flag: libreoffice-core. + * Add more -dbg package conflicts. Closes: #927745. + * Class data sharing is enabled during the build where available. + Just use the shipped classes.jsa files. Closes: #927441. + + -- Matthias Klose Thu, 25 Apr 2019 10:56:56 +0200 + openjdk-13 (13~17-2) experimental; urgency=medium * Fix the build of the -doc package. diff -Nru openjdk-13-13~17/debian/control openjdk-13-13~18/debian/control --- openjdk-13-13~17/debian/control 2019-04-19 01:00:51.000000000 +0000 +++ openjdk-13-13~18/debian/control 2019-04-24 10:49:45.000000000 +0000 @@ -60,7 +60,7 @@ java11-runtime-headless, java12-runtime-headless, java13-runtime-headless, ${defaultvm:Provides}, ${jvm:Provides} -Breaks: clojure1.8 (<= 1.8.0-7ubuntu1~) +Breaks: ${jrehl:Breaks} Conflicts: oracle-java11-installer, openjdk-11-jdk-headless (<< 11~18-2) Replaces: openjdk-11-jdk-headless (<< 11~18-2) Description: OpenJDK Java runtime, using ${vm:Name} (headless) @@ -151,7 +151,7 @@ ${misc:Depends} Recommends: openjdk-13-jre (= ${binary:Version}) Suggests: openjdk-13-jdk (= ${binary:Version}) -Conflicts: openjdk-11-dbg +Conflicts: openjdk-11-dbg, openjdk-12-dbg, Description: Java runtime based on OpenJDK (debugging symbols) OpenJDK is a development environment for building applications, applets, and components using the Java programming language. diff -Nru openjdk-13-13~17/debian/control.in openjdk-13-13~18/debian/control.in --- openjdk-13-13~17/debian/control.in 2019-04-01 23:49:26.000000000 +0000 +++ openjdk-13-13~18/debian/control.in 2019-04-24 10:49:39.000000000 +0000 @@ -60,7 +60,7 @@ java11-runtime-headless, java12-runtime-headless, java13-runtime-headless, ${defaultvm:Provides}, ${jvm:Provides} -Breaks: clojure1.8 (<= 1.8.0-7ubuntu1~) +Breaks: ${jrehl:Breaks} Conflicts: oracle-java11-installer, openjdk-11-jdk-headless (<< 11~18-2) Replaces: openjdk-11-jdk-headless (<< 11~18-2) Description: OpenJDK Java runtime, using ${vm:Name} (headless) @@ -151,7 +151,7 @@ ${misc:Depends} Recommends: @basename@-jre (= ${binary:Version}) Suggests: @basename@-jdk (= ${binary:Version}) -Conflicts: openjdk-11-dbg +Conflicts: openjdk-11-dbg, openjdk-12-dbg, Description: Java runtime based on OpenJDK (debugging symbols) OpenJDK is a development environment for building applications, applets, and components using the Java programming language. diff -Nru openjdk-13-13~17/debian/JB-jre-headless.postinst.in openjdk-13-13~18/debian/JB-jre-headless.postinst.in --- openjdk-13-13~17/debian/JB-jre-headless.postinst.in 2017-01-09 10:29:08.000000000 +0000 +++ openjdk-13-13~18/debian/JB-jre-headless.postinst.in 2019-04-25 08:43:15.000000000 +0000 @@ -93,32 +93,6 @@ update-binfmts --package @basename@ --import jar || true fi - # activate class data sharing - case @jvmarch@ in i386|i586|sparc) - rm -f $basedir/lib/client/classes.jsa - log=$(tempfile) - if ! $basedir/bin/java -client -Xshare:dump -XX:PermSize=128m > $log; then - cat >&2 $log - rm -f $log - # this may fail on some machines/configurations, just ignore it. - echo >&2 "ignoring dump failure" - #exit 1 - fi - rm -f $log - esac - case @jvmarch@ in amd64|i386|i586|sparc) - rm -f $basedir/lib/server/classes.jsa - log=$(tempfile) - if ! $basedir/bin/java -server -Xshare:dump > $log; then - cat >&2 $log - rm -f $log - # this may fail on some machines/configurations, just ignore it. - echo >&2 "ignoring dump failure" - #exit 1 - fi - rm -f $log - esac - ;; esac diff -Nru openjdk-13-13~17/debian/JB-jre-headless.prerm.in openjdk-13-13~18/debian/JB-jre-headless.prerm.in --- openjdk-13-13~17/debian/JB-jre-headless.prerm.in 2018-05-05 15:43:43.000000000 +0000 +++ openjdk-13-13~18/debian/JB-jre-headless.prerm.in 2019-04-25 08:43:38.000000000 +0000 @@ -19,8 +19,6 @@ fi update-alternatives --remove jexec $basedir/lib/jexec - - rm -f $basedir/lib/*/classes.jsa fi #DEBHELPER# diff -Nru openjdk-13-13~17/debian/rules openjdk-13-13~18/debian/rules --- openjdk-13-13~17/debian/rules 2019-04-19 01:00:51.000000000 +0000 +++ openjdk-13-13~18/debian/rules 2019-04-25 08:46:45.000000000 +0000 @@ -647,6 +647,24 @@ cjk_fonts += fonts-indic, endif +jrehl_breaks = clojure1.8 (<= 1.8.0-7ubuntu1~), +ifneq (,$(filter $(distrel),buster sid bionc cosmic disco eoan)) + jrehl_breaks += \ + jetty9 (<< 9.4.15-1~), netbeans (<< 10.0-3~), visualvm (<< 1.4.2-2~), \ + eclipse-platform (<< 3.8.1-11), +endif +ifneq (,$(filter $(distrel),bionc cosmic disco eoan)) + jrehl_breaks += \ + tomcat8 (<< 8.5.39-1ubuntu1~), +endif +ifneq (,$(filter $(distrel),buster sid)) + jrehl_breaks += \ + libreoffice-core (<< 1:6.1.5-2~), +else ifneq (,$(filter $(distrel),disco)) + jrehl_breaks += \ + libreoffice-core (<< 1:6.2.2-0ubuntu2), +endif + p_jre = $(basename)-jre p_jrehl = $(basename)-jre-headless p_jrez = $(basename)-jre-zero @@ -703,6 +721,8 @@ pkg_jcommon = java-common (>= 0.28) control_vars += '-Vjcommon:Depends=$(pkg_jcommon)' +control_vars += '-Vjrehl:Breaks=$(jrehl_breaks)' + debian/control: debian/control.in debian/rules @cp -p debian/control debian/control.old sed \ @@ -1680,7 +1700,7 @@ hg_project = jdk12 hg_tag = jdk-12+33 hg_project = jdk -hg_tag = jdk-13+17 +hg_tag = jdk-13+18 package_version = $(subst jdk-,,$(hg_tag)) ifneq ($(is_release),yes) package_version := $(subst +,~,$(package_version)) diff -Nru openjdk-13-13~17/doc/building.html openjdk-13-13~18/doc/building.html --- openjdk-13-13~17/doc/building.html 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/doc/building.html 2019-04-24 19:25:41.000000000 +0000 @@ -180,15 +180,15 @@ Linux -Oracle Enterprise Linux 6.4 / 7.1 (using kernel 3.8.13) +Oracle Enterprise Linux 6.4 / 7.6 Solaris -Solaris 11.1 SRU 21.4.1 / 11.2 SRU 5.5 +Solaris 11.3 macOS -Mac OS X 10.9 (Mavericks) / 10.10 (Yosemite) +Mac OS X 10.13 (High Sierra) Windows @@ -196,7 +196,7 @@ -

The double version numbers for Linux, Solaris and macOS is due to the hybrid model used at Oracle, where header files and external libraries from an older version are used when building on a more modern version of the OS.

+

The double version numbers for Linux and Solaris are due to the hybrid model used at Oracle, where header files and external libraries from an older version are used when building on a more modern version of the OS.

The Build Group has a wiki page with Supported Build Platforms. From time to time, this is updated by contributors to list successes or failures of building on different platforms.

Windows

Windows XP is not a supported platform, but all newer Windows should be able to build the JDK.

@@ -281,19 +281,19 @@ Linux -gcc 7.3.0 +gcc 8.2.0 macOS -Apple Xcode 9.4 (using clang 9.1.0) +Apple Xcode 10.1 (using clang 10.0.0) Solaris -Oracle Solaris Studio 12.4 (with compiler version 5.13) +Oracle Solaris Studio 12.6 (with compiler version 5.15) Windows -Microsoft Visual Studio 2017 update 15.5.5 +Microsoft Visual Studio 2017 update 15.9.6 diff -Nru openjdk-13-13~17/doc/building.md openjdk-13-13~18/doc/building.md --- openjdk-13-13~17/doc/building.md 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/doc/building.md 2019-04-24 19:25:41.000000000 +0000 @@ -150,14 +150,14 @@ Operating system Vendor/version used ----------------- ------------------------------------------------------- - Linux Oracle Enterprise Linux 6.4 / 7.1 (using kernel 3.8.13) - Solaris Solaris 11.1 SRU 21.4.1 / 11.2 SRU 5.5 - macOS Mac OS X 10.9 (Mavericks) / 10.10 (Yosemite) + Linux Oracle Enterprise Linux 6.4 / 7.6 + Solaris Solaris 11.3 SRU 20 + macOS Mac OS X 10.13 (High Sierra) Windows Windows Server 2012 R2 -The double version numbers for Linux, Solaris and macOS is due to the hybrid -model used at Oracle, where header files and external libraries from an older -version are used when building on a more modern version of the OS. +The double version numbers for Linux and Solaris are due to the hybrid model +used at Oracle, where header files and external libraries from an older version +are used when building on a more modern version of the OS. The Build Group has a wiki page with [Supported Build Platforms]( https://wiki.openjdk.java.net/display/Build/Supported+Build+Platforms). From @@ -323,10 +323,10 @@ Operating system Toolchain version ------------------ ------------------------------------------------------- - Linux gcc 7.3.0 - macOS Apple Xcode 9.4 (using clang 9.1.0) - Solaris Oracle Solaris Studio 12.4 (with compiler version 5.13) - Windows Microsoft Visual Studio 2017 update 15.5.5 + Linux gcc 8.2.0 + macOS Apple Xcode 10.1 (using clang 10.0.0) + Solaris Oracle Solaris Studio 12.6 (with compiler version 5.15) + Windows Microsoft Visual Studio 2017 update 15.9.6 ### gcc diff -Nru openjdk-13-13~17/.hg_archival.txt openjdk-13-13~18/.hg_archival.txt --- openjdk-13-13~17/.hg_archival.txt 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/.hg_archival.txt 2019-04-24 19:25:41.000000000 +0000 @@ -1,4 +1,4 @@ repo: fd16c54261b32be1aaedd863b7e856801b7f8543 -node: 93b702d2a0cb9e32160208f6700aede1f8492773 +node: bebb82ef3434a25f8142edafec20165f07ac562d branch: default -tag: jdk-13+17 +tag: jdk-13+18 diff -Nru openjdk-13-13~17/.hgtags openjdk-13-13~18/.hgtags --- openjdk-13-13~17/.hgtags 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/.hgtags 2019-04-24 19:25:41.000000000 +0000 @@ -554,3 +554,4 @@ 46cf212cdccaf4fb064d913b12004007d3322b67 jdk-13+14 f855ec13aa2501ae184c8b3e0626a8cec9966116 jdk-13+15 9d0ae9508d5337b0dc7cc4684be42888c4023755 jdk-13+16 +93b702d2a0cb9e32160208f6700aede1f8492773 jdk-13+17 diff -Nru openjdk-13-13~17/make/autoconf/libraries.m4 openjdk-13-13~18/make/autoconf/libraries.m4 --- openjdk-13-13~17/make/autoconf/libraries.m4 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/make/autoconf/libraries.m4 2019-04-24 19:25:41.000000000 +0000 @@ -130,6 +130,11 @@ BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lthread" fi + # perfstat lib + if test "x$OPENJDK_TARGET_OS" = xaix; then + BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lperfstat" + fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lsocket -lsched -ldoor -ldemangle -lnsl \ -lrt -lkstat" diff -Nru openjdk-13-13~17/make/CompileJavaModules.gmk openjdk-13-13~18/make/CompileJavaModules.gmk --- openjdk-13-13~17/make/CompileJavaModules.gmk 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/make/CompileJavaModules.gmk 2019-04-24 19:25:41.000000000 +0000 @@ -460,6 +460,7 @@ org.graalvm.compiler.core.test \ org.graalvm.compiler.debug.test \ org.graalvm.compiler.graph.test \ + org.graalvm.compiler.hotspot.aarch64.test \ org.graalvm.compiler.hotspot.amd64.test \ org.graalvm.compiler.hotspot.jdk9.test \ org.graalvm.compiler.hotspot.lir.test \ diff -Nru openjdk-13-13~17/make/test/JtregGraalUnit.gmk openjdk-13-13~18/make/test/JtregGraalUnit.gmk --- openjdk-13-13~17/make/test/JtregGraalUnit.gmk 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/make/test/JtregGraalUnit.gmk 2019-04-24 19:25:41.000000000 +0000 @@ -91,6 +91,7 @@ $(SRC_DIR)/org.graalvm.compiler.core.test/src \ $(SRC_DIR)/org.graalvm.compiler.debug.test/src \ $(SRC_DIR)/org.graalvm.compiler.graph.test/src \ + $(SRC_DIR)/org.graalvm.compiler.hotspot.aarch64.test/src \ $(SRC_DIR)/org.graalvm.compiler.hotspot.amd64.test/src \ $(SRC_DIR)/org.graalvm.compiler.hotspot.jdk9.test/src \ $(SRC_DIR)/org.graalvm.compiler.hotspot.lir.test/src \ diff -Nru openjdk-13-13~17/make/test/JtregNativeHotspot.gmk openjdk-13-13~18/make/test/JtregNativeHotspot.gmk --- openjdk-13-13~17/make/test/JtregNativeHotspot.gmk 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/make/test/JtregNativeHotspot.gmk 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -736,6 +736,7 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdisposeenv002 := $(NSK_JVMTI_AGENT_INCLUDES) BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdisposeenv001 := $(NSK_JVMTI_AGENT_INCLUDES) BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libexception001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libexceptionjni001 := $(NSK_JVMTI_AGENT_INCLUDES) BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libresexhausted := $(NSK_JVMTI_AGENT_INCLUDES) BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgcstart001 := $(NSK_JVMTI_AGENT_INCLUDES) BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgcstart002 := $(NSK_JVMTI_AGENT_INCLUDES) @@ -1375,6 +1376,7 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonenter004 += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonenter001 += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdealloc001 += -lpthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libexceptionjni001 += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisfldsin003 += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisfldsin002 += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrgrpinfo001 += -lpthread diff -Nru openjdk-13-13~17/src/hotspot/cpu/aarch64/aarch64.ad openjdk-13-13~18/src/hotspot/cpu/aarch64/aarch64.ad --- openjdk-13-13~17/src/hotspot/cpu/aarch64/aarch64.ad 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/cpu/aarch64/aarch64.ad 2019-04-24 19:25:41.000000000 +0000 @@ -11343,14 +11343,11 @@ instruct sbfmL(iRegLNoSp dst, iRegL src, immI lshift_count, immI rshift_count) %{ match(Set dst (RShiftL (LShiftL src lshift_count) rshift_count)); - // Make sure we are not going to exceed what sbfm can do. - predicate((unsigned int)n->in(2)->get_int() <= 63 - && (unsigned int)n->in(1)->in(2)->get_int() <= 63); - ins_cost(INSN_COST * 2); format %{ "sbfm $dst, $src, $rshift_count - $lshift_count, #63 - $lshift_count" %} ins_encode %{ - int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant; + int lshift = $lshift_count$$constant & 63; + int rshift = $rshift_count$$constant & 63; int s = 63 - lshift; int r = (rshift - lshift) & 63; __ sbfm(as_Register($dst$$reg), @@ -11366,14 +11363,11 @@ instruct sbfmwI(iRegINoSp dst, iRegIorL2I src, immI lshift_count, immI rshift_count) %{ match(Set dst (RShiftI (LShiftI src lshift_count) rshift_count)); - // Make sure we are not going to exceed what sbfmw can do. - predicate((unsigned int)n->in(2)->get_int() <= 31 - && (unsigned int)n->in(1)->in(2)->get_int() <= 31); - ins_cost(INSN_COST * 2); format %{ "sbfmw $dst, $src, $rshift_count - $lshift_count, #31 - $lshift_count" %} ins_encode %{ - int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant; + int lshift = $lshift_count$$constant & 31; + int rshift = $rshift_count$$constant & 31; int s = 31 - lshift; int r = (rshift - lshift) & 31; __ sbfmw(as_Register($dst$$reg), @@ -11389,14 +11383,11 @@ instruct ubfmL(iRegLNoSp dst, iRegL src, immI lshift_count, immI rshift_count) %{ match(Set dst (URShiftL (LShiftL src lshift_count) rshift_count)); - // Make sure we are not going to exceed what ubfm can do. - predicate((unsigned int)n->in(2)->get_int() <= 63 - && (unsigned int)n->in(1)->in(2)->get_int() <= 63); - ins_cost(INSN_COST * 2); format %{ "ubfm $dst, $src, $rshift_count - $lshift_count, #63 - $lshift_count" %} ins_encode %{ - int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant; + int lshift = $lshift_count$$constant & 63; + int rshift = $rshift_count$$constant & 63; int s = 63 - lshift; int r = (rshift - lshift) & 63; __ ubfm(as_Register($dst$$reg), @@ -11412,14 +11403,11 @@ instruct ubfmwI(iRegINoSp dst, iRegIorL2I src, immI lshift_count, immI rshift_count) %{ match(Set dst (URShiftI (LShiftI src lshift_count) rshift_count)); - // Make sure we are not going to exceed what ubfmw can do. - predicate((unsigned int)n->in(2)->get_int() <= 31 - && (unsigned int)n->in(1)->in(2)->get_int() <= 31); - ins_cost(INSN_COST * 2); format %{ "ubfmw $dst, $src, $rshift_count - $lshift_count, #31 - $lshift_count" %} ins_encode %{ - int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant; + int lshift = $lshift_count$$constant & 31; + int rshift = $rshift_count$$constant & 31; int s = 31 - lshift; int r = (rshift - lshift) & 31; __ ubfmw(as_Register($dst$$reg), @@ -11491,13 +11479,12 @@ instruct ubfizwI(iRegINoSp dst, iRegIorL2I src, immI lshift, immI_bitmask mask) %{ match(Set dst (LShiftI (AndI src mask) lshift)); - predicate((unsigned int)n->in(2)->get_int() <= 31 && - (exact_log2(n->in(1)->in(2)->get_int()+1) + (unsigned int)n->in(2)->get_int()) <= (31+1)); + predicate((exact_log2(n->in(1)->in(2)->get_int() + 1) + (n->in(2)->get_int() & 31)) <= (31 + 1)); ins_cost(INSN_COST); format %{ "ubfizw $dst, $src, $lshift, $mask" %} ins_encode %{ - int lshift = $lshift$$constant; + int lshift = $lshift$$constant & 31; long mask = $mask$$constant; int width = exact_log2(mask+1); __ ubfizw(as_Register($dst$$reg), @@ -11510,13 +11497,12 @@ instruct ubfizL(iRegLNoSp dst, iRegL src, immI lshift, immL_bitmask mask) %{ match(Set dst (LShiftL (AndL src mask) lshift)); - predicate((unsigned int)n->in(2)->get_int() <= 63 && - (exact_log2_long(n->in(1)->in(2)->get_long()+1) + (unsigned int)n->in(2)->get_int()) <= (63+1)); + predicate((exact_log2_long(n->in(1)->in(2)->get_long() + 1) + (n->in(2)->get_int() & 63)) <= (63 + 1)); ins_cost(INSN_COST); format %{ "ubfiz $dst, $src, $lshift, $mask" %} ins_encode %{ - int lshift = $lshift$$constant; + int lshift = $lshift$$constant & 63; long mask = $mask$$constant; int width = exact_log2_long(mask+1); __ ubfiz(as_Register($dst$$reg), @@ -11528,14 +11514,13 @@ // If there is a convert I to L block between and AndI and a LShiftL, we can also match ubfiz instruct ubfizIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI lshift, immI_bitmask mask) %{ - match(Set dst (LShiftL (ConvI2L(AndI src mask)) lshift)); - predicate((unsigned int)n->in(2)->get_int() <= 31 && - (exact_log2((unsigned int)n->in(1)->in(1)->in(2)->get_int()+1) + (unsigned int)n->in(2)->get_int()) <= 32); + match(Set dst (LShiftL (ConvI2L (AndI src mask)) lshift)); + predicate((exact_log2(n->in(1)->in(1)->in(2)->get_int() + 1) + (n->in(2)->get_int() & 63)) <= (63 + 1)); ins_cost(INSN_COST); format %{ "ubfiz $dst, $src, $lshift, $mask" %} ins_encode %{ - int lshift = $lshift$$constant; + int lshift = $lshift$$constant & 63; long mask = $mask$$constant; int width = exact_log2(mask+1); __ ubfiz(as_Register($dst$$reg), @@ -11549,7 +11534,7 @@ instruct extrOrL(iRegLNoSp dst, iRegL src1, iRegL src2, immI lshift, immI rshift, rFlagsReg cr) %{ match(Set dst (OrL (LShiftL src1 lshift) (URShiftL src2 rshift))); - predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 63)); + predicate(0 == (((n->in(1)->in(2)->get_int() & 63) + (n->in(2)->in(2)->get_int() & 63)) & 63)); ins_cost(INSN_COST); format %{ "extr $dst, $src1, $src2, #$rshift" %} @@ -11564,7 +11549,7 @@ instruct extrOrI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI lshift, immI rshift, rFlagsReg cr) %{ match(Set dst (OrI (LShiftI src1 lshift) (URShiftI src2 rshift))); - predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 31)); + predicate(0 == (((n->in(1)->in(2)->get_int() & 31) + (n->in(2)->in(2)->get_int() & 31)) & 31)); ins_cost(INSN_COST); format %{ "extr $dst, $src1, $src2, #$rshift" %} @@ -11579,7 +11564,7 @@ instruct extrAddL(iRegLNoSp dst, iRegL src1, iRegL src2, immI lshift, immI rshift, rFlagsReg cr) %{ match(Set dst (AddL (LShiftL src1 lshift) (URShiftL src2 rshift))); - predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 63)); + predicate(0 == (((n->in(1)->in(2)->get_int() & 63) + (n->in(2)->in(2)->get_int() & 63)) & 63)); ins_cost(INSN_COST); format %{ "extr $dst, $src1, $src2, #$rshift" %} @@ -11594,7 +11579,7 @@ instruct extrAddI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI lshift, immI rshift, rFlagsReg cr) %{ match(Set dst (AddI (LShiftI src1 lshift) (URShiftI src2 rshift))); - predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 31)); + predicate(0 == (((n->in(1)->in(2)->get_int() & 31) + (n->in(2)->in(2)->get_int() & 31)) & 31)); ins_cost(INSN_COST); format %{ "extr $dst, $src1, $src2, #$rshift" %} diff -Nru openjdk-13-13~17/src/hotspot/cpu/aarch64/aarch64_ad.m4 openjdk-13-13~18/src/hotspot/cpu/aarch64/aarch64_ad.m4 --- openjdk-13-13~17/src/hotspot/cpu/aarch64/aarch64_ad.m4 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/cpu/aarch64/aarch64_ad.m4 2019-04-24 19:25:41.000000000 +0000 @@ -154,14 +154,11 @@ instruct $4$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src, immI lshift_count, immI rshift_count) %{ match(Set dst EXTEND($1, $3, src, lshift_count, rshift_count)); - // Make sure we are not going to exceed what $4 can do. - predicate((unsigned int)n->in(2)->get_int() <= $2 - && (unsigned int)n->in(1)->in(2)->get_int() <= $2); - ins_cost(INSN_COST * 2); format %{ "$4 $dst, $src, $rshift_count - $lshift_count, #$2 - $lshift_count" %} ins_encode %{ - int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant; + int lshift = $lshift_count$$constant & $2; + int rshift = $rshift_count$$constant & $2; int s = $2 - lshift; int r = (rshift - lshift) & $2; __ $4(as_Register($dst$$reg), @@ -224,13 +221,12 @@ `instruct $2$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src, immI lshift, imm$1_bitmask mask) %{ match(Set dst (LShift$1 (And$1 src mask) lshift)); - predicate((unsigned int)n->in(2)->get_int() <= $3 && - (exact_log2$5(n->in(1)->in(2)->get_$4()+1) + (unsigned int)n->in(2)->get_int()) <= ($3+1)); + predicate((exact_log2$5(n->in(1)->in(2)->get_$4() + 1) + (n->in(2)->get_int() & $3)) <= ($3 + 1)); ins_cost(INSN_COST); format %{ "$2 $dst, $src, $lshift, $mask" %} ins_encode %{ - int lshift = $lshift$$constant; + int lshift = $lshift$$constant & $3; long mask = $mask$$constant; int width = exact_log2$5(mask+1); __ $2(as_Register($dst$$reg), @@ -239,19 +235,18 @@ ins_pipe(ialu_reg_shift); %}') UBFIZ_INSN(I, ubfizw, 31, int) -UBFIZ_INSN(L, ubfiz, 63, long, _long) +UBFIZ_INSN(L, ubfiz, 63, long, _long) // If there is a convert I to L block between and AndI and a LShiftL, we can also match ubfiz instruct ubfizIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI lshift, immI_bitmask mask) %{ - match(Set dst (LShiftL (ConvI2L(AndI src mask)) lshift)); - predicate((unsigned int)n->in(2)->get_int() <= 31 && - (exact_log2((unsigned int)n->in(1)->in(1)->in(2)->get_int()+1) + (unsigned int)n->in(2)->get_int()) <= 32); + match(Set dst (LShiftL (ConvI2L (AndI src mask)) lshift)); + predicate((exact_log2(n->in(1)->in(1)->in(2)->get_int() + 1) + (n->in(2)->get_int() & 63)) <= (63 + 1)); ins_cost(INSN_COST); format %{ "ubfiz $dst, $src, $lshift, $mask" %} ins_encode %{ - int lshift = $lshift$$constant; + int lshift = $lshift$$constant & 63; long mask = $mask$$constant; int width = exact_log2(mask+1); __ ubfiz(as_Register($dst$$reg), @@ -266,7 +261,7 @@ `instruct extr$3$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, immI lshift, immI rshift, rFlagsReg cr) %{ match(Set dst ($3$1 (LShift$1 src1 lshift) (URShift$1 src2 rshift))); - predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & $2)); + predicate(0 == (((n->in(1)->in(2)->get_int() & $2) + (n->in(2)->in(2)->get_int() & $2)) & $2)); ins_cost(INSN_COST); format %{ "extr $dst, $src1, $src2, #$rshift" %} diff -Nru openjdk-13-13~17/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp openjdk-13-13~18/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp --- openjdk-13-13~17/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -67,7 +67,11 @@ return false; } + // The CPU implementer codes can be found in + // ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile + // https://developer.arm.com/docs/ddi0487/latest enum Family { + CPU_AMPERE = 0xC0, CPU_ARM = 'A', CPU_BROADCOM = 'B', CPU_CAVIUM = 'C', diff -Nru openjdk-13-13~17/src/hotspot/cpu/ppc/vm_version_ppc.cpp openjdk-13-13~18/src/hotspot/cpu/ppc/vm_version_ppc.cpp --- openjdk-13-13~17/src/hotspot/cpu/ppc/vm_version_ppc.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/cpu/ppc/vm_version_ppc.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -38,6 +38,9 @@ #include "vm_version_ppc.hpp" #include +#if defined(_AIX) +#include +#endif #if defined(LINUX) && defined(VM_LITTLE_ENDIAN) #include @@ -382,6 +385,58 @@ } void VM_Version::print_platform_virtualization_info(outputStream* st) { +#if defined(_AIX) + // more info about perfstat API see + // https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.prftools/idprftools_perfstat_glob_partition.htm + int rc = 0; + perfstat_partition_total_t pinfo; + memset(&pinfo, 0, sizeof(perfstat_partition_total_t)); + rc = perfstat_partition_total(NULL, &pinfo, sizeof(perfstat_partition_total_t), 1); + if (rc != 1) { + return; + } else { + st->print_cr("Virtualization type : PowerVM"); + } + // CPU information + perfstat_cpu_total_t cpuinfo; + memset(&cpuinfo, 0, sizeof(perfstat_cpu_total_t)); + rc = perfstat_cpu_total(NULL, &cpuinfo, sizeof(perfstat_cpu_total_t), 1); + if (rc != 1) { + return; + } + + st->print_cr("Processor description : %s", cpuinfo.description); + st->print_cr("Processor speed : %llu Hz", cpuinfo.processorHZ); + + st->print_cr("LPAR partition name : %s", pinfo.name); + st->print_cr("LPAR partition number : %u", pinfo.lpar_id); + st->print_cr("LPAR partition type : %s", pinfo.type.b.shared_enabled ? "shared" : "dedicated"); + st->print_cr("LPAR mode : %s", pinfo.type.b.donate_enabled ? "donating" : pinfo.type.b.capped ? "capped" : "uncapped"); + st->print_cr("LPAR partition group ID : %u", pinfo.group_id); + st->print_cr("LPAR shared pool ID : %u", pinfo.pool_id); + + st->print_cr("AMS (active memory sharing) : %s", pinfo.type.b.ams_capable ? "capable" : "not capable"); + st->print_cr("AMS (active memory sharing) : %s", pinfo.type.b.ams_enabled ? "on" : "off"); + st->print_cr("AME (active memory expansion) : %s", pinfo.type.b.ame_enabled ? "on" : "off"); + + if (pinfo.type.b.ame_enabled) { + st->print_cr("AME true memory in bytes : %llu", pinfo.true_memory); + st->print_cr("AME expanded memory in bytes : %llu", pinfo.expanded_memory); + } + + st->print_cr("SMT : %s", pinfo.type.b.smt_capable ? "capable" : "not capable"); + st->print_cr("SMT : %s", pinfo.type.b.smt_enabled ? "on" : "off"); + int ocpus = pinfo.online_cpus > 0 ? pinfo.online_cpus : 1; + st->print_cr("LPAR threads : %d", cpuinfo.ncpus/ocpus); + st->print_cr("LPAR online virtual cpus : %d", pinfo.online_cpus); + st->print_cr("LPAR logical cpus : %d", cpuinfo.ncpus); + st->print_cr("LPAR maximum virtual cpus : %u", pinfo.max_cpus); + st->print_cr("LPAR minimum virtual cpus : %u", pinfo.min_cpus); + st->print_cr("LPAR entitled capacity : %4.2f", (double) (pinfo.entitled_proc_capacity/100.0)); + st->print_cr("LPAR online memory : %llu MB", pinfo.online_memory); + st->print_cr("LPAR maximum memory : %llu MB", pinfo.max_memory); + st->print_cr("LPAR minimum memory : %llu MB", pinfo.min_memory); +#else const char* info_file = "/proc/ppc64/lparcfg"; const char* kw[] = { "system_type=", // qemu indicates PowerKVM "partition_entitled_capacity=", // entitled processor capacity percentage @@ -400,6 +455,7 @@ if (!print_matching_lines_from_file(info_file, st, kw)) { st->print_cr(" <%s Not Available>", info_file); } +#endif } bool VM_Version::use_biased_locking() { diff -Nru openjdk-13-13~17/src/hotspot/os/aix/os_aix.cpp openjdk-13-13~18/src/hotspot/os/aix/os_aix.cpp --- openjdk-13-13~17/src/hotspot/os/aix/os_aix.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/os/aix/os_aix.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1405,13 +1405,7 @@ st->print_cr("type: %s", (wi.app_wpar ? "application" : "system")); } - // print partition info - libperfstat::partitioninfo_t pi; - if (libperfstat::get_partitioninfo(&pi)) { - st->print_cr("partition info"); - st->print_cr(" name: %s", pi.name); - } - + VM_Version::print_platform_virtualization_info(st); } void os::print_memory_info(outputStream* st) { diff -Nru openjdk-13-13~17/src/hotspot/os/linux/osContainer_linux.cpp openjdk-13-13~18/src/hotspot/os/linux/osContainer_linux.cpp --- openjdk-13-13~17/src/hotspot/os/linux/osContainer_linux.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/os/linux/osContainer_linux.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -122,7 +122,25 @@ char *subsystem_path() { return _path; } }; -CgroupSubsystem* memory = NULL; +class CgroupMemorySubsystem: CgroupSubsystem { + friend class OSContainer; + + private: + /* Some container runtimes set limits via cgroup + * hierarchy. If set to true consider also memory.stat + * file if everything else seems unlimited */ + bool _uses_mem_hierarchy; + + public: + CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) { + _uses_mem_hierarchy = false; + } + + bool is_hierarchical() { return _uses_mem_hierarchy; } + void set_hierarchical(bool value) { _uses_mem_hierarchy = value; } +}; + +CgroupMemorySubsystem* memory = NULL; CgroupSubsystem* cpuset = NULL; CgroupSubsystem* cpu = NULL; CgroupSubsystem* cpuacct = NULL; @@ -131,21 +149,24 @@ PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED -template int subsystem_file_contents(CgroupSubsystem* c, +template int subsystem_file_line_contents(CgroupSubsystem* c, const char *filename, + const char *matchline, const char *scan_fmt, T returnval) { FILE *fp = NULL; char *p; char file[MAXPATHLEN+1]; char buf[MAXPATHLEN+1]; + char discard[MAXPATHLEN+1]; + bool found_match = false; if (c == NULL) { - log_debug(os, container)("subsystem_file_contents: CgroupSubsytem* is NULL"); + log_debug(os, container)("subsystem_file_line_contents: CgroupSubsytem* is NULL"); return OSCONTAINER_ERROR; } if (c->subsystem_path() == NULL) { - log_debug(os, container)("subsystem_file_contents: subsystem path is NULL"); + log_debug(os, container)("subsystem_file_line_contents: subsystem path is NULL"); return OSCONTAINER_ERROR; } @@ -160,16 +181,32 @@ log_trace(os, container)("Path to %s is %s", filename, file); fp = fopen(file, "r"); if (fp != NULL) { - p = fgets(buf, MAXPATHLEN, fp); - if (p != NULL) { - int matched = sscanf(p, scan_fmt, returnval); - if (matched == 1) { + int err = 0; + while ((p = fgets(buf, MAXPATHLEN, fp)) != NULL) { + found_match = false; + if (matchline == NULL) { + // single-line file case + int matched = sscanf(p, scan_fmt, returnval); + found_match = (matched == 1); + } else { + // multi-line file case + if (strstr(p, matchline) != NULL) { + // discard matchline string prefix + int matched = sscanf(p, scan_fmt, discard, returnval); + found_match = (matched == 2); + } else { + continue; // substring not found + } + } + if (found_match) { fclose(fp); return 0; } else { + err = 1; log_debug(os, container)("Type %s not found in file %s", scan_fmt, file); } - } else { + } + if (err == 0) { log_debug(os, container)("Empty file %s", file); } } else { @@ -186,10 +223,11 @@ return_type variable; \ { \ int err; \ - err = subsystem_file_contents(subsystem, \ - filename, \ - scan_fmt, \ - &variable); \ + err = subsystem_file_line_contents(subsystem, \ + filename, \ + NULL, \ + scan_fmt, \ + &variable); \ if (err != 0) \ return (return_type) OSCONTAINER_ERROR; \ \ @@ -201,12 +239,29 @@ char variable[bufsize]; \ { \ int err; \ - err = subsystem_file_contents(subsystem, \ + err = subsystem_file_line_contents(subsystem, \ + filename, \ + NULL, \ + scan_fmt, \ + variable); \ + if (err != 0) \ + return (return_type) NULL; \ + \ + log_trace(os, container)(logstring, variable); \ +} + +#define GET_CONTAINER_INFO_LINE(return_type, subsystem, filename, \ + matchline, logstring, scan_fmt, variable) \ + return_type variable; \ +{ \ + int err; \ + err = subsystem_file_line_contents(subsystem, \ filename, \ + matchline, \ scan_fmt, \ - variable); \ + &variable); \ if (err != 0) \ - return (return_type) NULL; \ + return (return_type) OSCONTAINER_ERROR; \ \ log_trace(os, container)(logstring, variable); \ } @@ -266,7 +321,7 @@ } while ((token = strsep(&cptr, ",")) != NULL) { if (strcmp(token, "memory") == 0) { - memory = new CgroupSubsystem(tmproot, tmpmount); + memory = new CgroupMemorySubsystem(tmproot, tmpmount); } else if (strcmp(token, "cpuset") == 0) { cpuset = new CgroupSubsystem(tmproot, tmpmount); } else if (strcmp(token, "cpu") == 0) { @@ -344,6 +399,10 @@ while ((token = strsep(&controllers, ",")) != NULL) { if (strcmp(token, "memory") == 0) { memory->set_subsystem_path(base); + jlong hierarchy = uses_mem_hierarchy(); + if (hierarchy > 0) { + memory->set_hierarchical(true); + } } else if (strcmp(token, "cpuset") == 0) { cpuset->set_subsystem_path(base); } else if (strcmp(token, "cpu") == 0) { @@ -360,6 +419,7 @@ // command line arguments have been processed. if ((mem_limit = memory_limit_in_bytes()) > 0) { os::Linux::set_physical_memory(mem_limit); + log_info(os, container)("Memory Limit is: " JLONG_FORMAT, mem_limit); } _is_containerized = true; @@ -374,6 +434,21 @@ } } +/* uses_mem_hierarchy + * + * Return whether or not hierarchical cgroup accounting is being + * done. + * + * return: + * A number > 0 if true, or + * OSCONTAINER_ERROR for not supported + */ +jlong OSContainer::uses_mem_hierarchy() { + GET_CONTAINER_INFO(jlong, memory, "/memory.use_hierarchy", + "Use Hierarchy is: " JLONG_FORMAT, JLONG_FORMAT, use_hierarchy); + return use_hierarchy; +} + /* memory_limit_in_bytes * @@ -389,7 +464,18 @@ "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit); if (memlimit >= _unlimited_memory) { - log_trace(os, container)("Memory Limit is: Unlimited"); + log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited"); + if (memory->is_hierarchical()) { + const char* matchline = "hierarchical_memory_limit"; + char* format = "%s " JULONG_FORMAT; + GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline, + "Hierarchical Memory Limit is: " JULONG_FORMAT, format, hier_memlimit) + if (hier_memlimit >= _unlimited_memory) { + log_trace(os, container)("Hierarchical Memory Limit is: Unlimited"); + } else { + return (jlong)hier_memlimit; + } + } return (jlong)-1; } else { @@ -401,7 +487,18 @@ GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes", "Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit); if (memswlimit >= _unlimited_memory) { - log_trace(os, container)("Memory and Swap Limit is: Unlimited"); + log_trace(os, container)("Non-Hierarchical Memory and Swap Limit is: Unlimited"); + if (memory->is_hierarchical()) { + const char* matchline = "hierarchical_memsw_limit"; + char* format = "%s " JULONG_FORMAT; + GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline, + "Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, format, hier_memlimit) + if (hier_memlimit >= _unlimited_memory) { + log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited"); + } else { + return (jlong)hier_memlimit; + } + } return (jlong)-1; } else { return (jlong)memswlimit; diff -Nru openjdk-13-13~17/src/hotspot/os/linux/osContainer_linux.hpp openjdk-13-13~18/src/hotspot/os/linux/osContainer_linux.hpp --- openjdk-13-13~17/src/hotspot/os/linux/osContainer_linux.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/os/linux/osContainer_linux.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -42,6 +42,7 @@ static inline bool is_containerized(); static const char * container_type(); + static jlong uses_mem_hierarchy(); static jlong memory_limit_in_bytes(); static jlong memory_and_swap_limit_in_bytes(); static jlong memory_soft_limit_in_bytes(); diff -Nru openjdk-13-13~17/src/hotspot/os/windows/os_windows.cpp openjdk-13-13~18/src/hotspot/os/windows/os_windows.cpp --- openjdk-13-13~17/src/hotspot/os/windows/os_windows.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/os/windows/os_windows.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -5000,17 +5000,13 @@ char *addr, size_t bytes, bool read_only, bool allow_exec) { // This OS does not allow existing memory maps to be remapped so we - // have to unmap the memory before we remap it. - if (!os::unmap_memory(addr, bytes)) { - return NULL; - } + // would have to unmap the memory before we remap it. - // There is a very small theoretical window between the unmap_memory() - // call above and the map_memory() call below where a thread in native - // code may be able to access an address that is no longer mapped. - - return os::map_memory(fd, file_name, file_offset, addr, bytes, - read_only, allow_exec); + // Because there is a small window between unmapping memory and mapping + // it in again with different protections, CDS archives are mapped RW + // on windows, so this function isn't called. + ShouldNotReachHere(); + return NULL; } diff -Nru openjdk-13-13~17/src/hotspot/share/classfile/classFileParser.cpp openjdk-13-13~18/src/hotspot/share/classfile/classFileParser.cpp --- openjdk-13-13~17/src/hotspot/share/classfile/classFileParser.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/classfile/classFileParser.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -126,7 +126,8 @@ #define JAVA_13_VERSION 57 void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { - assert((bad_constant == 19 || bad_constant == 20) && _major_version >= JAVA_9_VERSION, + assert((bad_constant == JVM_CONSTANT_Module || + bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION, "Unexpected bad constant pool entry"); if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant; } @@ -343,8 +344,8 @@ } break; } - case 19: - case 20: { + case JVM_CONSTANT_Module: + case JVM_CONSTANT_Package: { // Record that an error occurred in these two cases but keep parsing so // that ACC_Module can be checked for in the access_flags. Need to // throw NoClassDefFoundError in that case. diff -Nru openjdk-13-13~17/src/hotspot/share/classfile/systemDictionary.cpp openjdk-13-13~18/src/hotspot/share/classfile/systemDictionary.cpp --- openjdk-13-13~17/src/hotspot/share/classfile/systemDictionary.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/classfile/systemDictionary.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -2750,106 +2750,61 @@ return Handle(THREAD, (oop) result.get_jobject()); } -// Ask Java to compute a constant by invoking a BSM given a Dynamic_info CP entry -Handle SystemDictionary::link_dynamic_constant(Klass* caller, - int condy_index, - Handle bootstrap_specifier, - Symbol* name, - Symbol* type, - TRAPS) { - Handle empty; - Handle bsm, info; - if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) { - bsm = bootstrap_specifier; - } else { - assert(bootstrap_specifier->is_objArray(), ""); - objArrayOop args = (objArrayOop) bootstrap_specifier(); - assert(args->length() == 2, ""); - bsm = Handle(THREAD, args->obj_at(0)); - info = Handle(THREAD, args->obj_at(1)); - } - guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()), - "caller must supply a valid BSM"); +// Ask Java to run a bootstrap method, in order to create a dynamic call site +// while linking an invokedynamic op, or compute a constant for Dynamic_info CP entry +// with linkage results being stored back into the bootstrap specifier. +void SystemDictionary::invoke_bootstrap_method(BootstrapInfo& bootstrap_specifier, TRAPS) { + // Resolve the bootstrap specifier, its name, type, and static arguments + bootstrap_specifier.resolve_bsm(CHECK); // This should not happen. JDK code should take care of that. - if (caller == NULL) { - THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad dynamic constant", empty); + if (bootstrap_specifier.caller() == NULL || bootstrap_specifier.type_arg().is_null()) { + THROW_MSG(vmSymbols::java_lang_InternalError(), "Invalid bootstrap method invocation with no caller or type argument"); } - Handle constant_name = java_lang_String::create_from_symbol(name, CHECK_(empty)); - - // Resolve the constant type in the context of the caller class - Handle type_mirror = find_java_mirror_for_type(type, caller, SignatureStream::NCDFError, - CHECK_(empty)); + bool is_indy = bootstrap_specifier.is_method_call(); + objArrayHandle appendix_box; + if (is_indy) { + // Some method calls may require an appendix argument. Arrange to receive it. + appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK); + assert(appendix_box->obj_at(0) == NULL, ""); + } - // call java.lang.invoke.MethodHandleNatives::linkConstantDyanmic(caller, condy_index, bsm, type, info) + // call condy: java.lang.invoke.MethodHandleNatives::linkDynamicConstant(caller, condy_index, bsm, type, info) + // indy: java.lang.invoke.MethodHandleNatives::linkCallSite(caller, indy_index, bsm, name, mtype, info, &appendix) JavaCallArguments args; - args.push_oop(Handle(THREAD, caller->java_mirror())); - args.push_int(condy_index); - args.push_oop(bsm); - args.push_oop(constant_name); - args.push_oop(type_mirror); - args.push_oop(info); + args.push_oop(Handle(THREAD, bootstrap_specifier.caller_mirror())); + args.push_int(bootstrap_specifier.bss_index()); + args.push_oop(bootstrap_specifier.bsm()); + args.push_oop(bootstrap_specifier.name_arg()); + args.push_oop(bootstrap_specifier.type_arg()); + args.push_oop(bootstrap_specifier.arg_values()); + if (is_indy) { + args.push_oop(appendix_box); + } JavaValue result(T_OBJECT); JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), - vmSymbols::linkDynamicConstant_name(), - vmSymbols::linkDynamicConstant_signature(), - &args, CHECK_(empty)); - - return Handle(THREAD, (oop) result.get_jobject()); -} - -// Ask Java code to find or construct a java.lang.invoke.CallSite for the given -// name and signature, as interpreted relative to the given class loader. -methodHandle SystemDictionary::find_dynamic_call_site_invoker(Klass* caller, - int indy_index, - Handle bootstrap_specifier, - Symbol* name, - Symbol* type, - Handle *appendix_result, - TRAPS) { - methodHandle empty; - Handle bsm, info; - if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) { - bsm = bootstrap_specifier; + is_indy ? vmSymbols::linkCallSite_name() : vmSymbols::linkDynamicConstant_name(), + is_indy ? vmSymbols::linkCallSite_signature() : vmSymbols::linkDynamicConstant_signature(), + &args, CHECK); + + Handle value(THREAD, (oop) result.get_jobject()); + if (is_indy) { + Handle appendix; + methodHandle method = unpack_method_and_appendix(value, + bootstrap_specifier.caller(), + appendix_box, + &appendix, CHECK); + bootstrap_specifier.set_resolved_method(method, appendix); } else { - objArrayOop args = (objArrayOop) bootstrap_specifier(); - assert(args->length() == 2, ""); - bsm = Handle(THREAD, args->obj_at(0)); - info = Handle(THREAD, args->obj_at(1)); + bootstrap_specifier.set_resolved_value(value); } - guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()), - "caller must supply a valid BSM"); - Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty)); - Handle method_type = find_method_handle_type(type, caller, CHECK_(empty)); - - // This should not happen. JDK code should take care of that. - if (caller == NULL || method_type.is_null()) { - THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty); - } - - objArrayHandle appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK_(empty)); - assert(appendix_box->obj_at(0) == NULL, ""); - - // call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, indy_index, bsm, name, mtype, info, &appendix) - JavaCallArguments args; - args.push_oop(Handle(THREAD, caller->java_mirror())); - args.push_int(indy_index); - args.push_oop(bsm); - args.push_oop(method_name); - args.push_oop(method_type); - args.push_oop(info); - args.push_oop(appendix_box); - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, - SystemDictionary::MethodHandleNatives_klass(), - vmSymbols::linkCallSite_name(), - vmSymbols::linkCallSite_signature(), - &args, CHECK_(empty)); - Handle mname(THREAD, (oop) result.get_jobject()); - return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD); + // sanity check + assert(bootstrap_specifier.is_resolved() || + (bootstrap_specifier.is_method_call() && + bootstrap_specifier.resolved_method().not_null()), "bootstrap method call failed"); } // Protection domain cache table handling diff -Nru openjdk-13-13~17/src/hotspot/share/classfile/systemDictionary.hpp openjdk-13-13~18/src/hotspot/share/classfile/systemDictionary.hpp --- openjdk-13-13~17/src/hotspot/share/classfile/systemDictionary.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/classfile/systemDictionary.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -74,6 +74,7 @@ // of placeholders must hold the SystemDictionary_lock. // +class BootstrapInfo; class ClassFileStream; class Dictionary; class PlaceholderTable; @@ -221,6 +222,7 @@ class SystemDictionary : AllStatic { + friend class BootstrapInfo; friend class VMStructs; friend class SystemDictionaryHandles; @@ -531,21 +533,7 @@ TRAPS); // ask Java to compute a constant by invoking a BSM given a Dynamic_info CP entry - static Handle link_dynamic_constant(Klass* caller, - int condy_index, - Handle bootstrap_specifier, - Symbol* name, - Symbol* type, - TRAPS); - - // ask Java to create a dynamic call site, while linking an invokedynamic op - static methodHandle find_dynamic_call_site_invoker(Klass* caller, - int indy_index, - Handle bootstrap_method, - Symbol* name, - Symbol* type, - Handle *appendix_result, - TRAPS); + static void invoke_bootstrap_method(BootstrapInfo& bootstrap_specifier, TRAPS); // Record the error when the first attempt to resolve a reference from a constant // pool entry to a class fails. diff -Nru openjdk-13-13~17/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp openjdk-13-13~18/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp --- openjdk-13-13~17/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -3135,20 +3135,24 @@ case Op_CompareAndSwapS: case Op_CompareAndSwapN: case Op_CompareAndSwapP: - case Op_ShenandoahCompareAndSwapN: - case Op_ShenandoahCompareAndSwapP: - case Op_ShenandoahWeakCompareAndSwapN: - case Op_ShenandoahWeakCompareAndSwapP: - case Op_ShenandoahCompareAndExchangeN: - case Op_ShenandoahCompareAndExchangeP: case Op_CompareAndExchangeL: case Op_CompareAndExchangeI: case Op_CompareAndExchangeB: case Op_CompareAndExchangeS: + case Op_CompareAndExchangeN: + case Op_CompareAndExchangeP: case Op_WeakCompareAndSwapL: case Op_WeakCompareAndSwapI: case Op_WeakCompareAndSwapB: case Op_WeakCompareAndSwapS: + case Op_WeakCompareAndSwapN: + case Op_WeakCompareAndSwapP: + case Op_ShenandoahCompareAndSwapN: + case Op_ShenandoahCompareAndSwapP: + case Op_ShenandoahWeakCompareAndSwapN: + case Op_ShenandoahWeakCompareAndSwapP: + case Op_ShenandoahCompareAndExchangeN: + case Op_ShenandoahCompareAndExchangeP: case Op_GetAndSetL: case Op_GetAndSetI: case Op_GetAndSetB: diff -Nru openjdk-13-13~17/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp openjdk-13-13~18/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp --- openjdk-13-13~17/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -30,22 +30,51 @@ #include "runtime/atomic.hpp" #include "utilities/copy.hpp" -ShenandoahCollectionSet::ShenandoahCollectionSet(ShenandoahHeap* heap, HeapWord* heap_base) : +ShenandoahCollectionSet::ShenandoahCollectionSet(ShenandoahHeap* heap, char* heap_base, size_t size) : _map_size(heap->num_regions()), _region_size_bytes_shift(ShenandoahHeapRegion::region_size_bytes_shift()), - _cset_map(NEW_C_HEAP_ARRAY(jbyte, _map_size, mtGC)), - _biased_cset_map(_cset_map - ((uintx)heap_base >> _region_size_bytes_shift)), + _map_space(align_up(((uintx)heap_base + size) >> _region_size_bytes_shift, os::vm_allocation_granularity())), + _cset_map(_map_space.base() + ((uintx)heap_base >> _region_size_bytes_shift)), + _biased_cset_map(_map_space.base()), _heap(heap), _garbage(0), _live_data(0), _used(0), _region_count(0), _current_index(0) { - // Use 1-byte data type - STATIC_ASSERT(sizeof(jbyte) == 1); - // Initialize cset map + // The collection set map is reserved to cover the entire heap *and* zero addresses. + // This is needed to accept in-cset checks for both heap oops and NULLs, freeing + // high-performance code from checking for NULL first. + // + // Since heap_base can be far away, committing the entire map would waste memory. + // Therefore, we only commit the parts that are needed to operate: the heap view, + // and the zero page. + // + // Note: we could instead commit the entire map, and piggyback on OS virtual memory + // subsystem for mapping not-yet-written-to pages to a single physical backing page, + // but this is not guaranteed, and would confuse NMT and other memory accounting tools. + + MemTracker::record_virtual_memory_type(_map_space.base(), mtGC); + + size_t page_size = (size_t)os::vm_page_size(); + + if (!_map_space.special()) { + // Commit entire pages that cover the heap cset map. + char* bot_addr = align_down(_cset_map, page_size); + char* top_addr = align_up(_cset_map + _map_size, page_size); + os::commit_memory_or_exit(bot_addr, pointer_delta(top_addr, bot_addr, 1), false, + "Unable to commit collection set bitmap: heap"); + + // Commit the zero page, if not yet covered by heap cset map. + if (bot_addr != _biased_cset_map) { + os::commit_memory_or_exit(_biased_cset_map, page_size, false, + "Unable to commit collection set bitmap: zero page"); + } + } + Copy::zero_to_bytes(_cset_map, _map_size); + Copy::zero_to_bytes(_biased_cset_map, page_size); } void ShenandoahCollectionSet::add_region(ShenandoahHeapRegion* r) { diff -Nru openjdk-13-13~17/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp openjdk-13-13~18/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp --- openjdk-13-13~17/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -33,9 +33,10 @@ private: size_t const _map_size; size_t const _region_size_bytes_shift; - jbyte* const _cset_map; + ReservedSpace _map_space; + char* const _cset_map; // Bias cset map's base address for fast test if an oop is in cset - jbyte* const _biased_cset_map; + char* const _biased_cset_map; ShenandoahHeap* const _heap; @@ -49,7 +50,7 @@ DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0); public: - ShenandoahCollectionSet(ShenandoahHeap* heap, HeapWord* heap_base); + ShenandoahCollectionSet(ShenandoahHeap* heap, char* heap_base, size_t size); // Add region to collection set void add_region(ShenandoahHeapRegion* r); @@ -88,7 +89,10 @@ void clear(); private: - jbyte* biased_map_address() const { + char* map_address() const { + return _cset_map; + } + char* biased_map_address() const { return _biased_cset_map; } }; diff -Nru openjdk-13-13~17/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp openjdk-13-13~18/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- openjdk-13-13~17/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -259,7 +259,7 @@ _regions = NEW_C_HEAP_ARRAY(ShenandoahHeapRegion*, _num_regions, mtGC); _free_set = new ShenandoahFreeSet(this, _num_regions); - _collection_set = new ShenandoahCollectionSet(this, (HeapWord*)sh_rs.base()); + _collection_set = new ShenandoahCollectionSet(this, sh_rs.base(), sh_rs.size()); { ShenandoahHeapLocker locker(lock()); @@ -537,6 +537,15 @@ p2i(reserved_region().start()), p2i(reserved_region().end())); + ShenandoahCollectionSet* cset = collection_set(); + st->print_cr("Collection set:"); + if (cset != NULL) { + st->print_cr(" - map (vanilla): " PTR_FORMAT, p2i(cset->map_address())); + st->print_cr(" - map (biased): " PTR_FORMAT, p2i(cset->biased_map_address())); + } else { + st->print_cr(" (NULL)"); + } + st->cr(); MetaspaceUtils::print_on(st); diff -Nru openjdk-13-13~17/src/hotspot/share/interpreter/bootstrapInfo.cpp openjdk-13-13~18/src/hotspot/share/interpreter/bootstrapInfo.cpp --- openjdk-13-13~17/src/hotspot/share/interpreter/bootstrapInfo.cpp 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/interpreter/bootstrapInfo.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "jvm.h" +#include "classfile/javaClasses.inline.hpp" +#include "classfile/resolutionErrors.hpp" +#include "interpreter/bootstrapInfo.hpp" +#include "interpreter/linkResolver.hpp" +#include "logging/log.hpp" +#include "logging/logStream.hpp" +#include "memory/oopFactory.hpp" +#include "oops/cpCache.inline.hpp" +#include "oops/objArrayOop.inline.hpp" +#include "oops/typeArrayOop.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/vmThread.hpp" + +//------------------------------------------------------------------------------------------------------------------------ +// Implementation of BootstrapInfo + +BootstrapInfo::BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index) + : _pool(pool), + _bss_index(bss_index), + _indy_index(indy_index), + // derived and eagerly cached: + _argc( pool->bootstrap_argument_count_at(bss_index) ), + _name( pool->uncached_name_ref_at(bss_index) ), + _signature( pool->uncached_signature_ref_at(bss_index) ) +{ + _is_resolved = false; + assert(pool->tag_at(bss_index).has_bootstrap(), ""); + assert(indy_index == -1 || pool->invokedynamic_bootstrap_ref_index_at(indy_index) == bss_index, "invalid bootstrap specifier index"); +} + +// If there is evidence this call site was already linked, set the +// existing linkage data into result, or throw previous exception. +// Return true if either action is taken, else false. +bool BootstrapInfo::resolve_previously_linked_invokedynamic(CallInfo& result, TRAPS) { + assert(_indy_index != -1, ""); + ConstantPoolCacheEntry* cpce = invokedynamic_cp_cache_entry(); + if (!cpce->is_f1_null()) { + methodHandle method( THREAD, cpce->f1_as_method()); + Handle appendix( THREAD, cpce->appendix_if_resolved(_pool)); + result.set_handle(method, appendix, THREAD); + Exceptions::wrap_dynamic_exception(CHECK_false); + return true; + } else if (cpce->indy_resolution_failed()) { + int encoded_index = ResolutionErrorTable::encode_cpcache_index(_indy_index); + ConstantPool::throw_resolution_error(_pool, encoded_index, CHECK_false); + return true; + } else { + return false; + } +} + +// Resolve the bootstrap specifier in 3 steps: +// - unpack the BSM by resolving the MH constant +// - obtain the NameAndType description for the condy/indy +// - prepare the BSM's static arguments +Handle BootstrapInfo::resolve_bsm(TRAPS) { + if (_bsm.not_null()) return _bsm; + // The tag at the bootstrap method index must be a valid method handle or a method handle in error. + // If it is a MethodHandleInError, a resolution error will be thrown which will be wrapped if necessary + // with a BootstrapMethodError. + assert(_pool->tag_at(bsm_index()).is_method_handle() || + _pool->tag_at(bsm_index()).is_method_handle_in_error(), "MH not present, classfile structural constraint"); + oop bsm_oop = _pool->resolve_possibly_cached_constant_at(bsm_index(), THREAD); + Exceptions::wrap_dynamic_exception(CHECK_NH); + guarantee(java_lang_invoke_MethodHandle::is_instance(bsm_oop), "classfile must supply a valid BSM"); + _bsm = Handle(THREAD, bsm_oop); + + // Obtain NameAndType information + resolve_bss_name_and_type(THREAD); + Exceptions::wrap_dynamic_exception(CHECK_NH); + + // Prepare static arguments + resolve_args(THREAD); + Exceptions::wrap_dynamic_exception(CHECK_NH); + + return _bsm; +} + +// Resolve metadata from the JVM_Dynamic_info or JVM_InvokeDynamic_info's name and type information. +void BootstrapInfo::resolve_bss_name_and_type(TRAPS) { + assert(_bsm.not_null(), "resolve_bsm first"); + Symbol* name = this->name(); + Symbol* type = this->signature(); + _name_arg = java_lang_String::create_from_symbol(name, CHECK); + if (type->char_at(0) == '(') { + _type_arg = SystemDictionary::find_method_handle_type(type, caller(), CHECK); + } else { + _type_arg = SystemDictionary::find_java_mirror_for_type(type, caller(), SignatureStream::NCDFError, CHECK); + } +} + +// Resolve the bootstrap method's static arguments and store the result in _arg_values. +void BootstrapInfo::resolve_args(TRAPS) { + assert(_bsm.not_null(), "resolve_bsm first"); + + // if there are no static arguments, return leaving _arg_values as null + if (_argc == 0 && UseBootstrapCallInfo < 2) return; + + bool use_BSCI; + switch (UseBootstrapCallInfo) { + default: use_BSCI = true; break; // stress mode + case 0: use_BSCI = false; break; // stress mode + case 1: // normal mode + // If we were to support an alternative mode of BSM invocation, + // we'd convert to pull mode here if the BSM could be a candidate + // for that alternative mode. We can't easily test for things + // like varargs here, but we can get away with approximate testing, + // since the JDK runtime will make up the difference either way. + // For now, exercise the pull-mode path if the BSM is of arity 2, + // or if there is a potential condy loop (see below). + oop mt_oop = java_lang_invoke_MethodHandle::type(_bsm()); + use_BSCI = (java_lang_invoke_MethodType::ptype_count(mt_oop) == 2); + break; + } + + // Here's a reason to use BSCI even if it wasn't requested: + // If a condy uses a condy argument, we want to avoid infinite + // recursion (condy loops) in the C code. It's OK in Java, + // because Java has stack overflow checking, so we punt + // potentially cyclic cases from C to Java. + if (!use_BSCI && _pool->tag_at(_bss_index).is_dynamic_constant()) { + bool found_unresolved_condy = false; + for (int i = 0; i < _argc; i++) { + int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i); + if (_pool->tag_at(arg_index).is_dynamic_constant()) { + // potential recursion point condy -> condy + bool found_it = false; + _pool->find_cached_constant_at(arg_index, found_it, CHECK); + if (!found_it) { found_unresolved_condy = true; break; } + } + } + if (found_unresolved_condy) + use_BSCI = true; + } + + const int SMALL_ARITY = 5; + if (use_BSCI && _argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) { + // If there are only a few arguments, and none of them need linking, + // push them, instead of asking the JDK runtime to turn around and + // pull them, saving a JVM/JDK transition in some simple cases. + bool all_resolved = true; + for (int i = 0; i < _argc; i++) { + bool found_it = false; + int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i); + _pool->find_cached_constant_at(arg_index, found_it, CHECK); + if (!found_it) { all_resolved = false; break; } + } + if (all_resolved) + use_BSCI = false; + } + + if (!use_BSCI) { + // return {arg...}; resolution of arguments is done immediately, before JDK code is called + objArrayOop args_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), _argc, CHECK); + objArrayHandle args(THREAD, args_oop); + _pool->copy_bootstrap_arguments_at(_bss_index, 0, _argc, args, 0, true, Handle(), CHECK); + oop arg_oop = ((_argc == 1) ? args->obj_at(0) : (oop)NULL); + // try to discard the singleton array + if (arg_oop != NULL && !arg_oop->is_array()) { + // JVM treats arrays and nulls specially in this position, + // but other things are just single arguments + _arg_values = Handle(THREAD, arg_oop); + } else { + _arg_values = args; + } + } else { + // return {arg_count, pool_index}; JDK code must pull the arguments as needed + typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK); + ints_oop->int_at_put(0, _argc); + ints_oop->int_at_put(1, _bss_index); + _arg_values = Handle(THREAD, ints_oop); + } +} + +// there must be a LinkageError pending; try to save it and then throw +bool BootstrapInfo::save_and_throw_indy_exc(TRAPS) { + assert(HAS_PENDING_EXCEPTION, ""); + assert(_indy_index != -1, ""); + ConstantPoolCacheEntry* cpce = invokedynamic_cp_cache_entry(); + int encoded_index = ResolutionErrorTable::encode_cpcache_index(_indy_index); + bool recorded_res_status = cpce->save_and_throw_indy_exc(_pool, _bss_index, + encoded_index, + pool()->tag_at(_bss_index), + CHECK_false); + return recorded_res_status; +} + +void BootstrapInfo::resolve_newly_linked_invokedynamic(CallInfo& result, TRAPS) { + assert(is_resolved(), ""); + result.set_handle(resolved_method(), resolved_appendix(), CHECK); +} + +void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) { + ResourceMark rm; + char what[20]; + st = st ? st : tty; + + if (_indy_index != -1) + sprintf(what, "indy#%d", decode_indy_index()); + else + sprintf(what, "condy"); + bool have_msg = (msg != NULL && strlen(msg) > 0); + st->print_cr("%s%sBootstrap in %s %s@CP[%d] %s:%s%s BSMS[%d] BSM@CP[%d]%s argc=%d%s", + (have_msg ? msg : ""), (have_msg ? " " : ""), + caller()->name()->as_C_string(), + what, // "indy#42" or "condy" + _bss_index, + _name->as_C_string(), + _signature->as_C_string(), + (_type_arg.is_null() ? "" : "(resolved)"), + bsms_attr_index(), + bsm_index(), (_bsm.is_null() ? "" : "(resolved)"), + _argc, (_arg_values.is_null() ? "" : "(resolved)")); + if (_argc > 0) { + char argbuf[80]; + argbuf[0] = 0; + for (int i = 0; i < _argc; i++) { + int pos = (int) strlen(argbuf); + if (pos + 20 > (int)sizeof(argbuf)) { + sprintf(argbuf + pos, "..."); + break; + } + if (i > 0) argbuf[pos++] = ','; + sprintf(argbuf+pos, "%d", arg_index(i)); + } + st->print_cr(" argument indexes: {%s}", argbuf); + } + if (_bsm.not_null()) { + st->print(" resolved BSM: "); _bsm->print(); + } + + // How the array of resolved arguments is printed depends highly + // on how BootstrapInfo::resolve_args structures the array based on + // the use_BSCI setting. + if (_arg_values.not_null()) { + // Find the static arguments within the first element of _arg_values. + objArrayOop static_args = (objArrayOop)_arg_values(); + if (!static_args->is_array()) { + assert(_argc == 1, "Invalid BSM _arg_values for non-array"); + st->print(" resolved arg[0]: "); static_args->print(); + } else if (static_args->is_objArray()) { + int lines = 0; + for (int i = 0; i < _argc; i++) { + oop x = static_args->obj_at(i); + if (x != NULL) { + if (++lines > 6) { + st->print_cr(" resolved arg[%d]: ...", i); + break; + } + st->print(" resolved arg[%d]: ", i); x->print(); + } + } + } else if (static_args->is_typeArray()) { + typeArrayOop tmp_array = (typeArrayOop) static_args; + assert(tmp_array->length() == 2, "Invalid BSM _arg_values type array"); + st->print_cr(" resolved arg[0]: %d", tmp_array->int_at(0)); + st->print_cr(" resolved arg[1]: %d", tmp_array->int_at(1)); + } + } +} diff -Nru openjdk-13-13~17/src/hotspot/share/interpreter/bootstrapInfo.hpp openjdk-13-13~18/src/hotspot/share/interpreter/bootstrapInfo.hpp --- openjdk-13-13~17/src/hotspot/share/interpreter/bootstrapInfo.hpp 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/interpreter/bootstrapInfo.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_INTERPRETER_BOOTSTRAPINFO_HPP +#define SHARE_INTERPRETER_BOOTSTRAPINFO_HPP + +#include "oops/constantPool.hpp" +#include "oops/instanceKlass.hpp" + +// BootstrapInfo provides condensed information from the constant pool +// necessary to invoke a bootstrap method. +class BootstrapInfo : public StackObj { + constantPoolHandle _pool; // constant pool containing the bootstrap specifier + const int _bss_index; // index of bootstrap specifier in CP (condy or indy) + const int _indy_index; // internal index of indy call site, or -1 if a condy call + const int _argc; // number of static arguments + Symbol* _name; // extracted from JVM_CONSTANT_NameAndType + Symbol* _signature; + + // pre-bootstrap resolution state: + Handle _bsm; // resolved bootstrap method + Handle _name_arg; // resolved String + Handle _type_arg; // resolved Class or MethodType + Handle _arg_values; // array of static arguments; null implies either + // uresolved or zero static arguments are specified + + // post-bootstrap resolution state: + bool _is_resolved; // set true when any of the next fields are set + Handle _resolved_value; // bind this as condy constant + methodHandle _resolved_method; // bind this as indy behavior + Handle _resolved_appendix; // extra opaque static argument for _resolved_method + + public: + BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index = -1); + + // accessors + const constantPoolHandle& pool() const{ return _pool; } + int bss_index() const { return _bss_index; } + int indy_index() const { return _indy_index; } + int argc() const { return _argc; } + bool is_method_call() const { return (_indy_index != -1); } + Symbol* name() const { return _name; } + Symbol* signature() const { return _signature; } + + // accessors to lazy state + Handle bsm() const { return _bsm; } + Handle name_arg() const { return _name_arg; } + Handle type_arg() const { return _type_arg; } + Handle arg_values() const { return _arg_values; } + bool is_resolved() const { return _is_resolved; } + Handle resolved_value() const { assert(!is_method_call(), ""); return _resolved_value; } + methodHandle resolved_method() const { assert(is_method_call(), ""); return _resolved_method; } + Handle resolved_appendix() const { assert(is_method_call(), ""); return _resolved_appendix; } + + // derived accessors + InstanceKlass* caller() const { return _pool->pool_holder(); } + oop caller_mirror() const { return caller()->java_mirror(); } + int decode_indy_index() const { return ConstantPool::decode_invokedynamic_index(_indy_index); } + int bsms_attr_index() const { return _pool->bootstrap_methods_attribute_index(_bss_index); } + int bsm_index() const { return _pool->bootstrap_method_ref_index_at(_bss_index); } + //int argc() is eagerly cached in _argc + int arg_index(int i) const { return _pool->bootstrap_argument_index_at(_bss_index, i); } + + // CP cache entry for call site (indy only) + ConstantPoolCacheEntry* invokedynamic_cp_cache_entry() const { + assert(is_method_call(), ""); + return _pool->invokedynamic_cp_cache_entry_at(_indy_index); + } + + // If there is evidence this call site was already linked, set the + // existing linkage data into result, or throw previous exception. + // Return true if either action is taken, else false. + bool resolve_previously_linked_invokedynamic(CallInfo& result, TRAPS); + bool save_and_throw_indy_exc(TRAPS); + void resolve_newly_linked_invokedynamic(CallInfo& result, TRAPS); + + // pre-bootstrap resolution actions: + Handle resolve_bsm(TRAPS); // lazily compute _bsm and return it + void resolve_bss_name_and_type(TRAPS); // lazily compute _name/_type + void resolve_args(TRAPS); // compute arguments + + // setters for post-bootstrap results: + void set_resolved_value(Handle value) { + assert(!is_resolved() && !is_method_call(), ""); + _is_resolved = true; + _resolved_value = value; + } + void set_resolved_method(methodHandle method, Handle appendix) { + assert(!is_resolved() && is_method_call(), ""); + _is_resolved = true; + _resolved_method = method; + _resolved_appendix = appendix; + } + + void print() { print_msg_on(tty); } + void print_msg_on(outputStream* st, const char* msg = NULL); +}; + +#endif // SHARE_INTERPRETER_BOOTSTRAPINFO_HPP diff -Nru openjdk-13-13~17/src/hotspot/share/interpreter/linkResolver.cpp openjdk-13-13~18/src/hotspot/share/interpreter/linkResolver.cpp --- openjdk-13-13~17/src/hotspot/share/interpreter/linkResolver.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/interpreter/linkResolver.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -32,6 +32,7 @@ #include "classfile/vmSymbols.hpp" #include "compiler/compileBroker.hpp" #include "gc/shared/collectedHeap.inline.hpp" +#include "interpreter/bootstrapInfo.hpp" #include "interpreter/bytecode.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/linkResolver.hpp" @@ -1694,99 +1695,80 @@ result.set_handle(resolved_klass, resolved_method, resolved_appendix, CHECK); } -void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { - Symbol* method_name = pool->name_ref_at(index); - Symbol* method_signature = pool->signature_ref_at(index); - Klass* current_klass = pool->pool_holder(); +void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int indy_index, TRAPS) { + ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(indy_index); + int pool_index = cpce->constant_pool_index(); // Resolve the bootstrap specifier (BSM + optional arguments). - Handle bootstrap_specifier; - // Check if CallSite has been bound already: - ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index); - int pool_index = cpce->constant_pool_index(); + BootstrapInfo bootstrap_specifier(pool, pool_index, indy_index); - if (cpce->is_f1_null()) { - if (cpce->indy_resolution_failed()) { - ConstantPool::throw_resolution_error(pool, - ResolutionErrorTable::encode_cpcache_index(index), - CHECK); - } - - // The initial step in Call Site Specifier Resolution is to resolve the symbolic - // reference to a method handle which will be the bootstrap method for a dynamic - // call site. If resolution for the java.lang.invoke.MethodHandle for the bootstrap - // method fails, then a MethodHandleInError is stored at the corresponding bootstrap - // method's CP index for the CONSTANT_MethodHandle_info. So, there is no need to - // set the indy_rf flag since any subsequent invokedynamic instruction which shares - // this bootstrap method will encounter the resolution of MethodHandleInError. - oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, THREAD); - Exceptions::wrap_dynamic_exception(CHECK); - assert(bsm_info != NULL, ""); - // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic. - bootstrap_specifier = Handle(THREAD, bsm_info); - } - if (!cpce->is_f1_null()) { - methodHandle method( THREAD, cpce->f1_as_method()); - Handle appendix( THREAD, cpce->appendix_if_resolved(pool)); - result.set_handle(method, appendix, THREAD); - Exceptions::wrap_dynamic_exception(CHECK); - return; - } + // Check if CallSite has been bound already or failed already, and short circuit: + { + bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(result, CHECK); + if (is_done) return; + } + + // The initial step in Call Site Specifier Resolution is to resolve the symbolic + // reference to a method handle which will be the bootstrap method for a dynamic + // call site. If resolution for the java.lang.invoke.MethodHandle for the bootstrap + // method fails, then a MethodHandleInError is stored at the corresponding bootstrap + // method's CP index for the CONSTANT_MethodHandle_info. So, there is no need to + // set the indy_rf flag since any subsequent invokedynamic instruction which shares + // this bootstrap method will encounter the resolution of MethodHandleInError. + + resolve_dynamic_call(result, bootstrap_specifier, CHECK); if (TraceMethodHandles) { - ResourceMark rm(THREAD); - tty->print_cr("resolve_invokedynamic #%d %s %s in %s", - ConstantPool::decode_invokedynamic_index(index), - method_name->as_C_string(), method_signature->as_C_string(), - current_klass->name()->as_C_string()); - tty->print(" BSM info: "); bootstrap_specifier->print(); - } - - resolve_dynamic_call(result, pool_index, bootstrap_specifier, method_name, - method_signature, current_klass, THREAD); - if (HAS_PENDING_EXCEPTION && PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { - int encoded_index = ResolutionErrorTable::encode_cpcache_index(index); - bool recorded_res_status = cpce->save_and_throw_indy_exc(pool, pool_index, - encoded_index, - pool()->tag_at(pool_index), - CHECK); - if (!recorded_res_status) { - // Another thread got here just before we did. So, either use the method - // that it resolved or throw the LinkageError exception that it threw. - if (!cpce->is_f1_null()) { - methodHandle method( THREAD, cpce->f1_as_method()); - Handle appendix( THREAD, cpce->appendix_if_resolved(pool)); - result.set_handle(method, appendix, THREAD); - Exceptions::wrap_dynamic_exception(CHECK); - } else { - assert(cpce->indy_resolution_failed(), "Resolution failure flag not set"); - ConstantPool::throw_resolution_error(pool, encoded_index, CHECK); - } - return; - } - assert(cpce->indy_resolution_failed(), "Resolution failure flag wasn't set"); + bootstrap_specifier.print_msg_on(tty, "resolve_invokedynamic"); } + + // The returned linkage result is provisional up to the moment + // the interpreter or runtime performs a serialized check of + // the relevant CPCE::f1 field. This is done by the caller + // of this method, via CPCE::set_dynamic_call, which uses + // an ObjectLocker to do the final serialization of updates + // to CPCE state, including f1. } void LinkResolver::resolve_dynamic_call(CallInfo& result, - int pool_index, - Handle bootstrap_specifier, - Symbol* method_name, Symbol* method_signature, - Klass* current_klass, + BootstrapInfo& bootstrap_specifier, TRAPS) { - // JSR 292: this must resolve to an implicitly generated method MH.linkToCallSite(*...) + // JSR 292: this must resolve to an implicitly generated method + // such as MH.linkToCallSite(*...) or some other call-site shape. // The appendix argument is likely to be a freshly-created CallSite. - Handle resolved_appendix; - methodHandle resolved_method = - SystemDictionary::find_dynamic_call_site_invoker(current_klass, - pool_index, - bootstrap_specifier, - method_name, method_signature, - &resolved_appendix, - THREAD); - Exceptions::wrap_dynamic_exception(CHECK); - result.set_handle(resolved_method, resolved_appendix, THREAD); - Exceptions::wrap_dynamic_exception(CHECK); + // It may also be a MethodHandle from an unwrapped ConstantCallSite, + // or any other reference. The resolved_method as well as the appendix + // are both recorded together via CallInfo::set_handle. + SystemDictionary::invoke_bootstrap_method(bootstrap_specifier, THREAD); + Exceptions::wrap_dynamic_exception(THREAD); + + if (HAS_PENDING_EXCEPTION) { + if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { + // Let any random low-level IE or SOE or OOME just bleed through. + // Basically we pretend that the bootstrap method was never called, + // if it fails this way: We neither record a successful linkage, + // nor do we memorize a LE for posterity. + return; + } + // JVMS 5.4.3 says: If an attempt by the Java Virtual Machine to resolve + // a symbolic reference fails because an error is thrown that is an + // instance of LinkageError (or a subclass), then subsequent attempts to + // resolve the reference always fail with the same error that was thrown + // as a result of the initial resolution attempt. + bool recorded_res_status = bootstrap_specifier.save_and_throw_indy_exc(CHECK); + if (!recorded_res_status) { + // Another thread got here just before we did. So, either use the method + // that it resolved or throw the LinkageError exception that it threw. + bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(result, CHECK); + if (is_done) return; + } + assert(bootstrap_specifier.invokedynamic_cp_cache_entry()->indy_resolution_failed(), + "Resolution failure flag wasn't set"); + } + + bootstrap_specifier.resolve_newly_linked_invokedynamic(result, CHECK); + // Exceptions::wrap_dynamic_exception not used because + // set_handle doesn't throw linkage errors } // Selected method is abstract. diff -Nru openjdk-13-13~17/src/hotspot/share/interpreter/linkResolver.hpp openjdk-13-13~18/src/hotspot/share/interpreter/linkResolver.hpp --- openjdk-13-13~17/src/hotspot/share/interpreter/linkResolver.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/interpreter/linkResolver.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -25,6 +25,7 @@ #ifndef SHARE_INTERPRETER_LINKRESOLVER_HPP #define SHARE_INTERPRETER_LINKRESOLVER_HPP +#include "interpreter/bootstrapInfo.hpp" #include "oops/method.hpp" // All the necessary definitions for run-time link resolution. @@ -77,6 +78,7 @@ CallKind kind, int index, TRAPS); + friend class BootstrapInfo; friend class LinkResolver; public: @@ -311,9 +313,8 @@ bool check_null_and_abstract, TRAPS); static void resolve_handle_call (CallInfo& result, const LinkInfo& link_info, TRAPS); - static void resolve_dynamic_call (CallInfo& result, int pool_index, Handle bootstrap_specifier, - Symbol* method_name, Symbol* method_signature, - Klass* current_klass, TRAPS); + static void resolve_dynamic_call (CallInfo& result, + BootstrapInfo& bootstrap_specifier, TRAPS); // same as above for compile-time resolution; but returns null handle instead of throwing // an exception on error also, does not initialize klass (i.e., no side effects) diff -Nru openjdk-13-13~17/src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.cpp openjdk-13-13~18/src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.cpp --- openjdk-13-13~17/src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "code/nmethod.hpp" #include "code/pcDesc.hpp" #include "jfr/periodic/sampling/jfrCallTrace.hpp" +#include "jfr/utilities/jfrTypes.hpp" #include "oops/method.hpp" #include "runtime/javaCalls.hpp" #include "runtime/frame.inline.hpp" @@ -37,7 +38,7 @@ assert(top_frame.cb() != NULL, "invariant"); RegisterMap map(_thread, false); frame candidate = top_frame; - for (int i = 0; i < MaxJavaStackTraceDepth * 2; ++i) { + for (u4 i = 0; i < MAX_STACK_DEPTH * 2; ++i) { if (candidate.is_entry_frame()) { JavaCallWrapper *jcw = candidate.entry_frame_call_wrapper_if_safe(_thread); if (jcw == NULL || jcw->is_first_frame()) { diff -Nru openjdk-13-13~17/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp openjdk-13-13~18/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp --- openjdk-13-13~17/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "jfr/recorder/service/jfrMemorySizer.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" #include "jfr/utilities/jfrAllocation.hpp" +#include "jfr/utilities/jfrTypes.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -106,10 +107,6 @@ return _stack_depth; } -static const u4 STACK_DEPTH_DEFAULT = 64; -static const u4 MIN_STACK_DEPTH = 1; -static const u4 MAX_STACK_DEPTH = 2048; - void JfrOptionSet::set_stackdepth(u4 depth) { if (depth < MIN_STACK_DEPTH) { _stack_depth = MIN_STACK_DEPTH; diff -Nru openjdk-13-13~17/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp openjdk-13-13~18/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp --- openjdk-13-13~17/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -69,8 +69,8 @@ } // handle general case - int loop_count = 0; - int loop_max = MaxJavaStackTraceDepth * 2; + u4 loop_count = 0; + u4 loop_max = MAX_STACK_DEPTH * 2; do { loop_count++; // By the time we get here we should never see unsafe but better safe then segv'd diff -Nru openjdk-13-13~17/src/hotspot/share/jfr/utilities/jfrTypes.hpp openjdk-13-13~18/src/hotspot/share/jfr/utilities/jfrTypes.hpp --- openjdk-13-13~17/src/hotspot/share/jfr/utilities/jfrTypes.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/jfr/utilities/jfrTypes.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -33,6 +33,9 @@ typedef int fio_fd; const int invalid_fd = -1; const jlong invalid_offset = -1; +const u4 STACK_DEPTH_DEFAULT = 64; +const u4 MIN_STACK_DEPTH = 1; +const u4 MAX_STACK_DEPTH = 2048; enum EventStartTime { UNTIMED, diff -Nru openjdk-13-13~17/src/hotspot/share/jvmci/vmStructs_jvmci.cpp openjdk-13-13~18/src/hotspot/share/jvmci/vmStructs_jvmci.cpp --- openjdk-13-13~17/src/hotspot/share/jvmci/vmStructs_jvmci.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/jvmci/vmStructs_jvmci.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -417,6 +417,8 @@ declare_constant(JVM_CONSTANT_MethodHandle) \ declare_constant(JVM_CONSTANT_MethodType) \ declare_constant(JVM_CONSTANT_InvokeDynamic) \ + declare_constant(JVM_CONSTANT_Module) \ + declare_constant(JVM_CONSTANT_Package) \ declare_constant(JVM_CONSTANT_ExternalMax) \ \ declare_constant(JVM_CONSTANT_Invalid) \ diff -Nru openjdk-13-13~17/src/hotspot/share/memory/filemap.cpp openjdk-13-13~18/src/hotspot/share/memory/filemap.cpp --- openjdk-13-13~17/src/hotspot/share/memory/filemap.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/memory/filemap.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -806,13 +806,14 @@ addr, size, false /* !read_only */, si->_allow_exec); close(); + // These have to be errors because the shared region is now unmapped. if (base == NULL) { - fail_continue("Unable to remap shared readonly space (errno=%d).", errno); - return false; + log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno); + vm_exit(1); } if (base != addr) { - fail_continue("Unable to remap shared readonly space at required address."); - return false; + log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno); + vm_exit(1); } si->_read_only = false; return true; @@ -849,10 +850,17 @@ size_t size = align_up(used, alignment); char *requested_addr = region_addr(i); - // If a tool agent is in use (debugging enabled), we must map the address space RW - if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) { +#ifdef _WINDOWS + // Windows cannot remap read-only shared memory to read-write when required for + // RedefineClasses, which is also used by JFR. Always map windows regions as RW. + si->_read_only = false; +#else + // If a tool agent is in use (debugging enabled), or JFR, we must map the address space RW + if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space() || + Arguments::has_jfr_option()) { si->_read_only = false; } +#endif // _WINDOWS // map the contents of the CDS archive in this memory char *base = os::map_memory(_fd, _full_path, si->_file_offset, @@ -868,7 +876,6 @@ MemTracker::record_virtual_memory_type((address)base, mtClassShared); #endif - if (!verify_region_checksum(i)) { return NULL; } diff -Nru openjdk-13-13~17/src/hotspot/share/memory/universe.cpp openjdk-13-13~18/src/hotspot/share/memory/universe.cpp --- openjdk-13-13~17/src/hotspot/share/memory/universe.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/memory/universe.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1151,6 +1151,8 @@ verify_flags |= Verify_JNIHandles; } else if (strcmp(token, "codecache_oops") == 0) { verify_flags |= Verify_CodeCacheOops; + } else if (strcmp(token, "resolved_method_table") == 0) { + verify_flags |= Verify_ResolvedMethodTable; } else { vm_exit_during_initialization(err_msg("VerifySubSet: \'%s\' memory sub-system is unknown, please correct it", token)); } @@ -1230,6 +1232,10 @@ log_debug(gc, verify)("CodeCache Oops"); CodeCache::verify_oops(); } + if (should_verify_subset(Verify_ResolvedMethodTable)) { + log_debug(gc, verify)("ResolvedMethodTable Oops"); + ResolvedMethodTable::verify(); + } _verify_in_progress = false; } diff -Nru openjdk-13-13~17/src/hotspot/share/memory/universe.hpp openjdk-13-13~18/src/hotspot/share/memory/universe.hpp --- openjdk-13-13~17/src/hotspot/share/memory/universe.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/memory/universe.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -478,6 +478,7 @@ Verify_MetaspaceUtils = 128, Verify_JNIHandles = 256, Verify_CodeCacheOops = 512, + Verify_ResolvedMethodTable = 1024, Verify_All = -1 }; static void initialize_verify_flags(); diff -Nru openjdk-13-13~17/src/hotspot/share/oops/constantPool.cpp openjdk-13-13~18/src/hotspot/share/oops/constantPool.cpp --- openjdk-13-13~17/src/hotspot/share/oops/constantPool.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/oops/constantPool.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -30,6 +30,7 @@ #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" +#include "interpreter/bootstrapInfo.hpp" #include "interpreter/linkResolver.hpp" #include "memory/allocation.inline.hpp" #include "memory/heapInspection.hpp" @@ -909,9 +910,8 @@ case JVM_CONSTANT_Dynamic: { - Klass* current_klass = this_cp->pool_holder(); - Symbol* constant_name = this_cp->uncached_name_ref_at(index); - Symbol* constant_type = this_cp->uncached_signature_ref_at(index); + // Resolve the Dynamically-Computed constant to invoke the BSM in order to obtain the resulting oop. + BootstrapInfo bootstrap_specifier(this_cp, index); // The initial step in resolving an unresolved symbolic reference to a // dynamically-computed constant is to resolve the symbolic reference to a @@ -921,27 +921,18 @@ // bootstrap method's CP index for the CONSTANT_MethodHandle_info. No need to // set a DynamicConstantInError here since any subsequent use of this // bootstrap method will encounter the resolution of MethodHandleInError. - oop bsm_info = this_cp->resolve_bootstrap_specifier_at(index, THREAD); - Exceptions::wrap_dynamic_exception(CHECK_NULL); - assert(bsm_info != NULL, ""); - // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_Dynamic. - Handle bootstrap_specifier = Handle(THREAD, bsm_info); - - // Resolve the Dynamically-Computed constant to invoke the BSM in order to obtain the resulting oop. - Handle value = SystemDictionary::link_dynamic_constant(current_klass, - index, - bootstrap_specifier, - constant_name, - constant_type, - THREAD); - result_oop = value(); + // Both the first, (resolution of the BSM and its static arguments), and the second tasks, + // (invocation of the BSM), of JVMS Section 5.4.3.6 occur within invoke_bootstrap_method() + // for the bootstrap_specifier created above. + SystemDictionary::invoke_bootstrap_method(bootstrap_specifier, THREAD); Exceptions::wrap_dynamic_exception(THREAD); if (HAS_PENDING_EXCEPTION) { // Resolution failure of the dynamically-computed constant, save_and_throw_exception // will check for a LinkageError and store a DynamicConstantInError. save_and_throw_exception(this_cp, index, tag, CHECK_NULL); } - BasicType type = FieldType::basic_type(constant_type); + result_oop = bootstrap_specifier.resolved_value()(); + BasicType type = FieldType::basic_type(bootstrap_specifier.signature()); if (!is_reference_type(type)) { // Make sure the primitive value is properly boxed. // This is a JDK responsibility. @@ -961,6 +952,10 @@ THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), fail); } } + + if (TraceMethodHandles) { + bootstrap_specifier.print_msg_on(tty, "resolve_constant_at_impl"); + } break; } @@ -1102,119 +1097,6 @@ return str; } - -oop ConstantPool::resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS) { - assert((this_cp->tag_at(index).is_invoke_dynamic() || - this_cp->tag_at(index).is_dynamic_constant()), "Corrupted constant pool"); - Handle bsm; - int argc; - { - // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&mtype], plus optional arguments - // JVM_CONSTANT_Dynamic is an ordered pair of [bootm, name&ftype], plus optional arguments - // In both cases, the bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry. - // It is accompanied by the optional arguments. - int bsm_index = this_cp->bootstrap_method_ref_index_at(index); - oop bsm_oop = this_cp->resolve_possibly_cached_constant_at(bsm_index, CHECK_NULL); - if (!java_lang_invoke_MethodHandle::is_instance(bsm_oop)) { - THROW_MSG_NULL(vmSymbols::java_lang_LinkageError(), "BSM not an MethodHandle"); - } - - // Extract the optional static arguments. - argc = this_cp->bootstrap_argument_count_at(index); - - // if there are no static arguments, return the bsm by itself: - if (argc == 0 && UseBootstrapCallInfo < 2) return bsm_oop; - - bsm = Handle(THREAD, bsm_oop); - } - - // We are going to return an ordered pair of {bsm, info}, using a 2-array. - objArrayHandle info; - { - objArrayOop info_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), 2, CHECK_NULL); - info = objArrayHandle(THREAD, info_oop); - } - - info->obj_at_put(0, bsm()); - - bool use_BSCI; - switch (UseBootstrapCallInfo) { - default: use_BSCI = true; break; // stress mode - case 0: use_BSCI = false; break; // stress mode - case 1: // normal mode - // If we were to support an alternative mode of BSM invocation, - // we'd convert to pull mode here if the BSM could be a candidate - // for that alternative mode. We can't easily test for things - // like varargs here, but we can get away with approximate testing, - // since the JDK runtime will make up the difference either way. - // For now, exercise the pull-mode path if the BSM is of arity 2, - // or if there is a potential condy loop (see below). - oop mt_oop = java_lang_invoke_MethodHandle::type(bsm()); - use_BSCI = (java_lang_invoke_MethodType::ptype_count(mt_oop) == 2); - break; - } - - // Here's a reason to use BSCI even if it wasn't requested: - // If a condy uses a condy argument, we want to avoid infinite - // recursion (condy loops) in the C code. It's OK in Java, - // because Java has stack overflow checking, so we punt - // potentially cyclic cases from C to Java. - if (!use_BSCI && this_cp->tag_at(index).is_dynamic_constant()) { - bool found_unresolved_condy = false; - for (int i = 0; i < argc; i++) { - int arg_index = this_cp->bootstrap_argument_index_at(index, i); - if (this_cp->tag_at(arg_index).is_dynamic_constant()) { - // potential recursion point condy -> condy - bool found_it = false; - this_cp->find_cached_constant_at(arg_index, found_it, CHECK_NULL); - if (!found_it) { found_unresolved_condy = true; break; } - } - } - if (found_unresolved_condy) - use_BSCI = true; - } - - const int SMALL_ARITY = 5; - if (use_BSCI && argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) { - // If there are only a few arguments, and none of them need linking, - // push them, instead of asking the JDK runtime to turn around and - // pull them, saving a JVM/JDK transition in some simple cases. - bool all_resolved = true; - for (int i = 0; i < argc; i++) { - bool found_it = false; - int arg_index = this_cp->bootstrap_argument_index_at(index, i); - this_cp->find_cached_constant_at(arg_index, found_it, CHECK_NULL); - if (!found_it) { all_resolved = false; break; } - } - if (all_resolved) - use_BSCI = false; - } - - if (!use_BSCI) { - // return {bsm, {arg...}}; resolution of arguments is done immediately, before JDK code is called - objArrayOop args_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), argc, CHECK_NULL); - info->obj_at_put(1, args_oop); // may overwrite with args[0] below - objArrayHandle args(THREAD, args_oop); - copy_bootstrap_arguments_at_impl(this_cp, index, 0, argc, args, 0, true, Handle(), CHECK_NULL); - if (argc == 1) { - // try to discard the singleton array - oop arg_oop = args->obj_at(0); - if (arg_oop != NULL && !arg_oop->is_array()) { - // JVM treats arrays and nulls specially in this position, - // but other things are just single arguments - info->obj_at_put(1, arg_oop); - } - } - } else { - // return {bsm, {arg_count, pool_index}}; JDK code must pull the arguments as needed - typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK_NULL); - ints_oop->int_at_put(0, argc); - ints_oop->int_at_put(1, index); - info->obj_at_put(1, ints_oop); - } - return info(); -} - void ConstantPool::copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int index, int start_arg, int end_arg, objArrayHandle info, int pos, @@ -1848,8 +1730,8 @@ } // end compare_operand_to() // Search constant pool search_cp for a bootstrap specifier that matches -// this constant pool's bootstrap specifier at pattern_i index. -// Return the index of a matching bootstrap specifier or (-1) if there is no match. +// this constant pool's bootstrap specifier data at pattern_i index. +// Return the index of a matching bootstrap attribute record or (-1) if there is no match. int ConstantPool::find_matching_operand(int pattern_i, const constantPoolHandle& search_cp, int search_len, TRAPS) { for (int i = 0; i < search_len; i++) { @@ -1858,7 +1740,7 @@ return i; } } - return -1; // bootstrap specifier not found; return unused index (-1) + return -1; // bootstrap specifier data not found; return unused index (-1) } // end find_matching_operand() diff -Nru openjdk-13-13~17/src/hotspot/share/oops/constantPool.hpp openjdk-13-13~18/src/hotspot/share/oops/constantPool.hpp --- openjdk-13-13~17/src/hotspot/share/oops/constantPool.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/oops/constantPool.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -746,11 +746,6 @@ return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, &found_it, THREAD); } - oop resolve_bootstrap_specifier_at(int index, TRAPS) { - constantPoolHandle h_this(THREAD, this); - return resolve_bootstrap_specifier_at_impl(h_this, index, THREAD); - } - void copy_bootstrap_arguments_at(int index, int start_arg, int end_arg, objArrayHandle info, int pos, @@ -871,7 +866,6 @@ static oop resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index, bool* status_return, TRAPS); - static oop resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS); static void copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int index, int start_arg, int end_arg, objArrayHandle info, int pos, diff -Nru openjdk-13-13~17/src/hotspot/share/oops/markOop.cpp openjdk-13-13~18/src/hotspot/share/oops/markOop.cpp --- openjdk-13-13~17/src/hotspot/share/oops/markOop.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/oops/markOop.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,9 +37,9 @@ if (mon == NULL) { st->print("NULL (this should never be seen!)"); } else { - st->print("{count=0x%08x,waiters=0x%08x" + st->print("{contentions=0x%08x,waiters=0x%08x" ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}", - mon->count(), mon->waiters(), mon->recursions(), + mon->contentions(), mon->waiters(), mon->recursions(), p2i(mon->owner())); } } else if (is_locked()) { diff -Nru openjdk-13-13~17/src/hotspot/share/prims/jvmtiRedefineClasses.cpp openjdk-13-13~18/src/hotspot/share/prims/jvmtiRedefineClasses.cpp --- openjdk-13-13~17/src/hotspot/share/prims/jvmtiRedefineClasses.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/prims/jvmtiRedefineClasses.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -787,6 +787,12 @@ return JVMTI_ERROR_NONE; } +static bool can_add_or_delete(Method* m) { + // Compatibility mode + return (AllowRedefinitionToAddDeleteMethods && + (m->is_private() && (m->is_static() || m->is_final()))); +} + jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( InstanceKlass* the_class, InstanceKlass* scratch_class) { @@ -992,12 +998,7 @@ break; case added: // method added, see if it is OK - new_flags = (jushort) k_new_method->access_flags().get_flags(); - if ((new_flags & JVM_ACC_PRIVATE) == 0 - // hack: private should be treated as final, but alas - || (new_flags & (JVM_ACC_FINAL|JVM_ACC_STATIC)) == 0 - ) { - // new methods must be private + if (!can_add_or_delete(k_new_method)) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED; } { @@ -1026,12 +1027,7 @@ break; case deleted: // method deleted, see if it is OK - old_flags = (jushort) k_old_method->access_flags().get_flags(); - if ((old_flags & JVM_ACC_PRIVATE) == 0 - // hack: private should be treated as final, but alas - || (old_flags & (JVM_ACC_FINAL|JVM_ACC_STATIC)) == 0 - ) { - // deleted methods must be private + if (!can_add_or_delete(k_old_method)) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED; } log_trace(redefine, class, normalize) diff -Nru openjdk-13-13~17/src/hotspot/share/prims/resolvedMethodTable.cpp openjdk-13-13~18/src/hotspot/share/prims/resolvedMethodTable.cpp --- openjdk-13-13~17/src/hotspot/share/prims/resolvedMethodTable.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/prims/resolvedMethodTable.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -346,16 +346,6 @@ // cleaning. Note it might trigger a resize instead. void ResolvedMethodTable::finish_dead_counter() { check_concurrent_work(); - -#ifdef ASSERT - if (SafepointSynchronize::is_at_safepoint()) { - size_t fail_cnt = verify_and_compare_entries(); - if (fail_cnt != 0) { - tty->print_cr("ERROR: fail_cnt=" SIZE_FORMAT, fail_cnt); - guarantee(fail_cnt == 0, "unexpected ResolvedMethodTable verification failures"); - } - } -#endif // ASSERT } #if INCLUDE_JVMTI @@ -402,26 +392,16 @@ } #endif // INCLUDE_JVMTI -// Verification and comp -class VerifyCompResolvedMethod : StackObj { - GrowableArray* _oops; +// Verification +class VerifyResolvedMethod : StackObj { public: - size_t _errors; - VerifyCompResolvedMethod(GrowableArray* oops) : _oops(oops), _errors(0) {} bool operator()(WeakHandle* val) { - oop s = val->peek(); - if (s == NULL) { - return true; + oop obj = val->peek(); + if (obj != NULL) { + Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(obj); + guarantee(method->is_method(), "Must be"); + guarantee(!method->is_old(), "Must be"); } - int len = _oops->length(); - for (int i = 0; i < len; i++) { - bool eq = s == _oops->at(i); - assert(!eq, "Duplicate entries"); - if (eq) { - _errors++; - } - } - _oops->push(s); return true; }; }; @@ -430,16 +410,9 @@ return _items_count; } -size_t ResolvedMethodTable::verify_and_compare_entries() { - Thread* thr = Thread::current(); - GrowableArray* oops = - new (ResourceObj::C_HEAP, mtInternal) - GrowableArray((int)_current_size, true); - - VerifyCompResolvedMethod vcs(oops); - if (!_local_table->try_scan(thr, vcs)) { +void ResolvedMethodTable::verify() { + VerifyResolvedMethod vcs; + if (!_local_table->try_scan(Thread::current(), vcs)) { log_info(membername, table)("verify unavailable at this moment"); } - delete oops; - return vcs._errors; } diff -Nru openjdk-13-13~17/src/hotspot/share/prims/resolvedMethodTable.hpp openjdk-13-13~18/src/hotspot/share/prims/resolvedMethodTable.hpp --- openjdk-13-13~17/src/hotspot/share/prims/resolvedMethodTable.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/prims/resolvedMethodTable.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -96,7 +96,7 @@ // Debugging static size_t items_count(); - static size_t verify_and_compare_entries(); + static void verify(); }; #endif // SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP diff -Nru openjdk-13-13~17/src/hotspot/share/runtime/arguments.cpp openjdk-13-13~18/src/hotspot/share/runtime/arguments.cpp --- openjdk-13-13~17/src/hotspot/share/runtime/arguments.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/runtime/arguments.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -271,17 +271,25 @@ } #if INCLUDE_JFR +static bool _has_jfr_option = false; // is using JFR + // return true on failure static bool match_jfr_option(const JavaVMOption** option) { assert((*option)->optionString != NULL, "invariant"); char* tail = NULL; if (match_option(*option, "-XX:StartFlightRecording", (const char**)&tail)) { + _has_jfr_option = true; return Jfr::on_start_flight_recording_option(option, tail); } else if (match_option(*option, "-XX:FlightRecorderOptions", (const char**)&tail)) { + _has_jfr_option = true; return Jfr::on_flight_recorder_option(option, tail); } return false; } + +bool Arguments::has_jfr_option() { + return _has_jfr_option; +} #endif static void logOption(const char* opt) { @@ -532,6 +540,7 @@ { "FailOverToOldVerifier", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() }, { "AllowJNIEnvProxy", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) }, { "ThreadLocalHandshakes", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) }, + { "AllowRedefinitionToAddDeleteMethods", JDK_Version::jdk(13), JDK_Version::undefined(), JDK_Version::undefined() }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() }, diff -Nru openjdk-13-13~17/src/hotspot/share/runtime/arguments.hpp openjdk-13-13~18/src/hotspot/share/runtime/arguments.hpp --- openjdk-13-13~17/src/hotspot/share/runtime/arguments.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/runtime/arguments.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -649,6 +649,8 @@ static bool check_unsupported_cds_runtime_properties() NOT_CDS_RETURN0; static bool atojulong(const char *s, julong* result); + + static bool has_jfr_option() NOT_JFR_RETURN_(false); }; // Disable options not supported in this release, with a warning if they diff -Nru openjdk-13-13~17/src/hotspot/share/runtime/globals.hpp openjdk-13-13~18/src/hotspot/share/runtime/globals.hpp --- openjdk-13-13~17/src/hotspot/share/runtime/globals.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/runtime/globals.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -545,10 +545,10 @@ "Number of ring buffer event logs") \ range(1, NOT_LP64(1*K) LP64_ONLY(1*M)) \ \ - product(bool, BytecodeVerificationRemote, true, \ + diagnostic(bool, BytecodeVerificationRemote, true, \ "Enable the Java bytecode verifier for remote classes") \ \ - product(bool, BytecodeVerificationLocal, false, \ + diagnostic(bool, BytecodeVerificationLocal, false, \ "Enable the Java bytecode verifier for local classes") \ \ develop(bool, ForceFloatExceptions, trueInDebug, \ @@ -978,6 +978,10 @@ product(bool, VerifyMergedCPBytecodes, true, \ "Verify bytecodes after RedefineClasses constant pool merging") \ \ + product(bool, AllowRedefinitionToAddDeleteMethods, false, \ + "Allow redefinition to add and delete private static or " \ + "final methods for compatibility with old releases") \ + \ develop(bool, TraceBytecodes, false, \ "Trace bytecode execution") \ \ diff -Nru openjdk-13-13~17/src/hotspot/share/runtime/objectMonitor.cpp openjdk-13-13~18/src/hotspot/share/runtime/objectMonitor.cpp --- openjdk-13-13~17/src/hotspot/share/runtime/objectMonitor.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/runtime/objectMonitor.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -276,9 +276,13 @@ // Note that if we acquire the monitor from an initial spin // we forgo posting JVMTI events and firing DTRACE probes. if (TrySpin(Self) > 0) { - assert(_owner == Self, "invariant"); - assert(_recursions == 0, "invariant"); - assert(((oop)(object()))->mark() == markOopDesc::encode(this), "invariant"); + assert(_owner == Self, "must be Self: owner=" INTPTR_FORMAT, p2i(_owner)); + assert(_recursions == 0, "must be 0: recursions=" INTPTR_FORMAT, + _recursions); + assert(((oop)object())->mark() == markOopDesc::encode(this), + "object mark must match encoded this: mark=" INTPTR_FORMAT + ", encoded this=" INTPTR_FORMAT, p2i(((oop)object())->mark()), + p2i(markOopDesc::encode(this))); Self->_Stalled = 0; return; } @@ -290,11 +294,11 @@ assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); assert(jt->thread_state() != _thread_blocked, "invariant"); assert(this->object() != NULL, "invariant"); - assert(_count >= 0, "invariant"); + assert(_contentions >= 0, "invariant"); // Prevent deflation at STW-time. See deflate_idle_monitors() and is_busy(). // Ensure the object-monitor relationship remains stable while there's contention. - Atomic::inc(&_count); + Atomic::inc(&_contentions); JFR_ONLY(JfrConditionalFlushWithStacktrace flush(jt);) EventJavaMonitorEnter event; @@ -355,8 +359,8 @@ // acquire it. } - Atomic::dec(&_count); - assert(_count >= 0, "invariant"); + Atomic::dec(&_contentions); + assert(_contentions >= 0, "invariant"); Self->_Stalled = 0; // Must either set _recursions = 0 or ASSERT _recursions == 0. @@ -809,7 +813,7 @@ // There's one exception to the claim above, however. EnterI() can call // exit() to drop a lock if the acquirer has been externally suspended. // In that case exit() is called with _thread_state as _thread_blocked, -// but the monitor's _count field is > 0, which inhibits reclamation. +// but the monitor's _contentions field is > 0, which inhibits reclamation. // // 1-0 exit // ~~~~~~~~ diff -Nru openjdk-13-13~17/src/hotspot/share/runtime/objectMonitor.hpp openjdk-13-13~18/src/hotspot/share/runtime/objectMonitor.hpp --- openjdk-13-13~17/src/hotspot/share/runtime/objectMonitor.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/runtime/objectMonitor.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -163,9 +163,9 @@ volatile int _Spinner; // for exit->spinner handoff optimization volatile int _SpinDuration; - volatile jint _count; // reference count to prevent reclamation/deflation - // at stop-the-world time. See ObjectSynchronizer::deflate_monitor(). - // _count is approximately |_WaitSet| + |_EntryList| + volatile jint _contentions; // Number of active contentions in enter(). It is used by is_busy() + // along with other fields to determine if an ObjectMonitor can be + // deflated. See ObjectSynchronizer::deflate_monitor(). protected: ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor volatile jint _waiters; // number of waiting threads @@ -207,7 +207,6 @@ static int header_offset_in_bytes() { return offset_of(ObjectMonitor, _header); } static int object_offset_in_bytes() { return offset_of(ObjectMonitor, _object); } static int owner_offset_in_bytes() { return offset_of(ObjectMonitor, _owner); } - static int count_offset_in_bytes() { return offset_of(ObjectMonitor, _count); } static int recursions_offset_in_bytes() { return offset_of(ObjectMonitor, _recursions); } static int cxq_offset_in_bytes() { return offset_of(ObjectMonitor, _cxq); } static int succ_offset_in_bytes() { return offset_of(ObjectMonitor, _succ); } @@ -232,10 +231,8 @@ void set_header(markOop hdr); intptr_t is_busy() const { - // TODO-FIXME: merge _count and _waiters. // TODO-FIXME: assert _owner == null implies _recursions = 0 - // TODO-FIXME: assert _WaitSet != null implies _count > 0 - return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList); + return _contentions|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList); } intptr_t is_entered(Thread* current) const; @@ -245,8 +242,6 @@ jint waiters() const; - jint count() const; - void set_count(jint count); jint contentions() const; intptr_t recursions() const { return _recursions; } @@ -263,14 +258,14 @@ ~ObjectMonitor() { // TODO: Add asserts ... // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 - // _count == 0 _EntryList == NULL etc + // _contentions == 0 _EntryList == NULL etc } private: void Recycle() { // TODO: add stronger asserts ... // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 - // _count == 0 EntryList == NULL + // _contentions == 0 EntryList == NULL // _recursions == 0 _WaitSet == NULL assert(((is_busy()|_recursions) == 0), "freeing inuse monitor"); _succ = NULL; diff -Nru openjdk-13-13~17/src/hotspot/share/runtime/objectMonitor.inline.hpp openjdk-13-13~18/src/hotspot/share/runtime/objectMonitor.inline.hpp --- openjdk-13-13~17/src/hotspot/share/runtime/objectMonitor.inline.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/runtime/objectMonitor.inline.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -45,10 +45,6 @@ _header = hdr; } -inline jint ObjectMonitor::count() const { - return _count; -} - inline jint ObjectMonitor::waiters() const { return _waiters; } @@ -58,12 +54,12 @@ } inline void ObjectMonitor::clear() { - assert(_header != NULL, "Fatal logic error in ObjectMonitor header!"); - assert(_count == 0, "Fatal logic error in ObjectMonitor count!"); - assert(_waiters == 0, "Fatal logic error in ObjectMonitor waiters!"); - assert(_recursions == 0, "Fatal logic error in ObjectMonitor recursions!"); - assert(_object != NULL, "Fatal logic error in ObjectMonitor object!"); - assert(_owner == NULL, "Fatal logic error in ObjectMonitor owner!"); + assert(_header != NULL, "must be non-NULL"); + assert(_contentions == 0, "must be 0: contentions=%d", _contentions); + assert(_waiters == 0, "must be 0: waiters=%d", _waiters); + assert(_recursions == 0, "must be 0: recursions=" INTPTR_FORMAT, _recursions); + assert(_object != NULL, "must be non-NULL"); + assert(_owner == NULL, "must be NULL: owner=" INTPTR_FORMAT, p2i(_owner)); _header = NULL; _object = NULL; @@ -96,10 +92,10 @@ // return number of threads contending for this monitor inline jint ObjectMonitor::contentions() const { - return _count; + return _contentions; } -// Do NOT set _count = 0. There is a race such that _count could +// Do NOT set _contentions = 0. There is a race such that _contentions could // be set while inflating prior to setting _owner // Just use Atomic::inc/dec and assert 0 when monitor put on free list inline void ObjectMonitor::set_owner(void* owner) { diff -Nru openjdk-13-13~17/src/hotspot/share/runtime/synchronizer.cpp openjdk-13-13~18/src/hotspot/share/runtime/synchronizer.cpp --- openjdk-13-13~17/src/hotspot/share/runtime/synchronizer.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/runtime/synchronizer.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -735,7 +735,7 @@ } else if (mark->has_monitor()) { monitor = mark->monitor(); temp = monitor->header(); - assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp)); + assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp)); hash = temp->hash(); if (hash != 0) { return hash; @@ -743,39 +743,38 @@ // Skip to the following code to reduce code size } else if (Self->is_lock_owned((address)mark->locker())) { temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned - assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp)); + assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp)); hash = temp->hash(); // by current thread, check if the displaced if (hash != 0) { // header contains hash code return hash; } // WARNING: - // The displaced header is strictly immutable. - // It can NOT be changed in ANY cases. So we have - // to inflate the header into heavyweight monitor - // even the current thread owns the lock. The reason - // is the BasicLock (stack slot) will be asynchronously - // read by other threads during the inflate() function. - // Any change to stack may not propagate to other threads - // correctly. + // The displaced header in the BasicLock on a thread's stack + // is strictly immutable. It CANNOT be changed in ANY cases. + // So we have to inflate the stack lock into an ObjectMonitor + // even if the current thread owns the lock. The BasicLock on + // a thread's stack can be asynchronously read by other threads + // during an inflate() call so any change to that stack memory + // may not propagate to other threads correctly. } // Inflate the monitor to set hash code monitor = inflate(Self, obj, inflate_cause_hash_code); // Load displaced header and check it has hash code mark = monitor->header(); - assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)mark)); + assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark)); hash = mark->hash(); if (hash == 0) { hash = get_next_hash(Self, obj); temp = mark->copy_set_hash(hash); // merge hash code into header - assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp)); + assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp)); test = Atomic::cmpxchg(temp, monitor->header_addr(), mark); if (test != mark) { - // The only update to the header in the monitor (outside GC) - // is install the hash code. If someone add new usage of - // displaced header, please update this code + // The only update to the ObjectMonitor's header/dmw field + // is to merge in the hash code. If someone adds a new usage + // of the header/dmw field, please update this code. hash = test->hash(); - assert(test->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)test)); + assert(test->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(test)); assert(hash != 0, "Trivial unexpected object/monitor header usage."); } } @@ -1334,7 +1333,7 @@ if (mark->has_monitor()) { ObjectMonitor * inf = mark->monitor(); markOop dmw = inf->header(); - assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)dmw)); + assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw)); assert(oopDesc::equals((oop) inf->object(), object), "invariant"); assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid"); return inf; @@ -1398,7 +1397,7 @@ // Consider what happens when a thread unlocks a stack-locked object. // It attempts to use CAS to swing the displaced header value from the // on-stack basiclock back into the object header. Recall also that the - // header value (hashcode, etc) can reside in (a) the object header, or + // header value (hash code, etc) can reside in (a) the object header, or // (b) a displaced header associated with the stack-lock, or (c) a displaced // header in an objectMonitor. The inflate() routine must copy the header // value from the basiclock on the owner's stack to the objectMonitor, all @@ -1419,7 +1418,9 @@ // object is in the mark. Furthermore the owner can't complete // an unlock on the object, either. markOop dmw = mark->displaced_mark_helper(); - assert(dmw->is_neutral(), "invariant"); + // Catch if the object's header is not neutral (not locked and + // not marked is what we care about here). + assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw)); // Setup monitor fields to proper values -- prepare the monitor m->set_header(dmw); @@ -1463,7 +1464,9 @@ // An inflateTry() method that we could call from fast_enter() and slow_enter() // would be useful. - assert(mark->is_neutral(), "invariant"); + // Catch if the object's header is not neutral (not locked and + // not marked is what we care about here). + assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark)); ObjectMonitor * m = omAlloc(Self); // prepare m for installation - set monitor to initial state m->Recycle(); @@ -1503,7 +1506,7 @@ } -// We create a list of in-use monitors for each thread. +// We maintain a list of in-use monitors for each thread. // // deflate_thread_local_monitors() scans a single thread's in-use list, while // deflate_idle_monitors() scans only a global list of in-use monitors which @@ -1512,7 +1515,7 @@ // These operations are called at all safepoints, immediately after mutators // are stopped, but before any objects have moved. Collectively they traverse // the population of in-use monitors, deflating where possible. The scavenged -// monitors are returned to the monitor free list. +// monitors are returned to the global monitor free list. // // Beware that we scavenge at *every* stop-the-world point. Having a large // number of monitors in-use could negatively impact performance. We also want @@ -1521,7 +1524,7 @@ // // Perversely, the heap size -- and thus the STW safepoint rate -- // typically drives the scavenge rate. Large heaps can mean infrequent GC, -// which in turn can mean large(r) numbers of objectmonitors in circulation. +// which in turn can mean large(r) numbers of ObjectMonitors in circulation. // This is an unfortunate aspect of this design. // Deflate a single monitor if not in-use @@ -1531,9 +1534,15 @@ ObjectMonitor** freeTailp) { bool deflated; // Normal case ... The monitor is associated with obj. - guarantee(obj->mark() == markOopDesc::encode(mid), "invariant"); - guarantee(mid == obj->mark()->monitor(), "invariant"); - guarantee(mid->header()->is_neutral(), "invariant"); + const markOop mark = obj->mark(); + guarantee(mark == markOopDesc::encode(mid), "should match: mark=" + INTPTR_FORMAT ", encoded mid=" INTPTR_FORMAT, p2i(mark), + p2i(markOopDesc::encode(mid))); + // Make sure that mark->monitor() and markOopDesc::encode() agree: + guarantee(mark->monitor() == mid, "should match: monitor()=" INTPTR_FORMAT + ", mid=" INTPTR_FORMAT, p2i(mark->monitor()), p2i(mid)); + const markOop dmw = mid->header(); + guarantee(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw)); if (mid->is_busy()) { deflated = false; @@ -1544,16 +1553,17 @@ if (log_is_enabled(Trace, monitorinflation)) { ResourceMark rm; log_trace(monitorinflation)("deflate_monitor: " - "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'", - p2i(obj), p2i(obj->mark()), - obj->klass()->external_name()); + "object=" INTPTR_FORMAT ", mark=" + INTPTR_FORMAT ", type='%s'", p2i(obj), + p2i(mark), obj->klass()->external_name()); } // Restore the header back to obj - obj->release_set_mark(mid->header()); + obj->release_set_mark(dmw); mid->clear(); - assert(mid->object() == NULL, "invariant"); + assert(mid->object() == NULL, "invariant: object=" INTPTR_FORMAT, + p2i(mid->object())); // Move the object to the working free list defined by freeHeadp, freeTailp if (*freeHeadp == NULL) *freeHeadp = mid; @@ -2022,13 +2032,12 @@ out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT ": in-use per-thread monitor's object does not think " "it has a monitor: obj=" INTPTR_FORMAT ", mark=" - INTPTR_FORMAT, p2i(jt), p2i(n), p2i((address)obj), - p2i((address)mark)); + INTPTR_FORMAT, p2i(jt), p2i(n), p2i(obj), p2i(mark)); } else { out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global " "monitor's object does not think it has a monitor: obj=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT, p2i(n), - p2i((address)obj), p2i((address)mark)); + p2i(obj), p2i(mark)); } *error_cnt_p = *error_cnt_p + 1; } @@ -2039,14 +2048,12 @@ ": in-use per-thread monitor's object does not refer " "to the same monitor: obj=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", obj_mon=" INTPTR_FORMAT, p2i(jt), - p2i(n), p2i((address)obj), p2i((address)mark), - p2i((address)obj_mon)); + p2i(n), p2i(obj), p2i(mark), p2i(obj_mon)); } else { out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global " "monitor's object does not refer to the same monitor: obj=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", obj_mon=" - INTPTR_FORMAT, p2i(n), p2i((address)obj), - p2i((address)mark), p2i((address)obj_mon)); + INTPTR_FORMAT, p2i(n), p2i(obj), p2i(mark), p2i(obj_mon)); } *error_cnt_p = *error_cnt_p + 1; } @@ -2105,7 +2112,7 @@ if (gOmInUseCount > 0) { out->print_cr("In-use global monitor info:"); - out->print_cr("(B -> is_busy, H -> has hashcode, L -> lock status)"); + out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)"); out->print_cr("%18s %s %18s %18s", "monitor", "BHL", "object", "object type"); out->print_cr("================== === ================== =================="); @@ -2124,7 +2131,7 @@ } out->print_cr("In-use per-thread monitor info:"); - out->print_cr("(B -> is_busy, H -> has hashcode, L -> lock status)"); + out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)"); out->print_cr("%18s %18s %s %18s %18s", "jt", "monitor", "BHL", "object", "object type"); out->print_cr("================== ================== === ================== =================="); diff -Nru openjdk-13-13~17/src/hotspot/share/runtime/vmStructs.cpp openjdk-13-13~18/src/hotspot/share/runtime/vmStructs.cpp --- openjdk-13-13~17/src/hotspot/share/runtime/vmStructs.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/runtime/vmStructs.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -896,7 +896,7 @@ volatile_nonstatic_field(ObjectMonitor, _header, markOop) \ unchecked_nonstatic_field(ObjectMonitor, _object, sizeof(void *)) /* NOTE: no type */ \ unchecked_nonstatic_field(ObjectMonitor, _owner, sizeof(void *)) /* NOTE: no type */ \ - volatile_nonstatic_field(ObjectMonitor, _count, jint) \ + volatile_nonstatic_field(ObjectMonitor, _contentions, jint) \ volatile_nonstatic_field(ObjectMonitor, _waiters, jint) \ volatile_nonstatic_field(ObjectMonitor, _recursions, intptr_t) \ nonstatic_field(ObjectMonitor, FreeNext, ObjectMonitor*) \ @@ -2095,6 +2095,8 @@ declare_constant(JVM_CONSTANT_MethodType) \ declare_constant(JVM_CONSTANT_Dynamic) \ declare_constant(JVM_CONSTANT_InvokeDynamic) \ + declare_constant(JVM_CONSTANT_Module) \ + declare_constant(JVM_CONSTANT_Package) \ declare_constant(JVM_CONSTANT_ExternalMax) \ \ declare_constant(JVM_CONSTANT_Invalid) \ diff -Nru openjdk-13-13~17/src/hotspot/share/utilities/macros.hpp openjdk-13-13~18/src/hotspot/share/utilities/macros.hpp --- openjdk-13-13~17/src/hotspot/share/utilities/macros.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/hotspot/share/utilities/macros.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -279,8 +279,10 @@ #if INCLUDE_JFR #define JFR_ONLY(code) code +#define NOT_JFR_RETURN_(code) /* next token must be ; */ #else #define JFR_ONLY(code) +#define NOT_JFR_RETURN_(code) { return code; } #endif #ifndef INCLUDE_JVMCI diff -Nru openjdk-13-13~17/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java openjdk-13-13~18/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java --- openjdk-13-13~17/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,15 +25,16 @@ package jdk.internal.platform.cgroupv1; -import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; +import jdk.internal.platform.cgroupv1.SubSystem.MemorySubSystem; + public class Metrics implements jdk.internal.platform.Metrics { - private SubSystem memory; + private MemorySubSystem memory; private SubSystem cpu; private SubSystem cpuacct; private SubSystem cpuset; @@ -133,7 +134,7 @@ for (String subsystemName: subsystemNames) { switch (subsystemName) { case "memory": - metric.setMemorySubSystem(new SubSystem(mountentry[3], mountentry[4])); + metric.setMemorySubSystem(new MemorySubSystem(mountentry[3], mountentry[4])); break; case "cpuset": metric.setCpuSetSubSystem(new SubSystem(mountentry[3], mountentry[4])); @@ -195,6 +196,11 @@ if (subsystem != null) { subsystem.setPath(base); + if (subsystem instanceof MemorySubSystem) { + MemorySubSystem memorySubSystem = (MemorySubSystem)subsystem; + boolean isHierarchial = getHierarchical(memorySubSystem); + memorySubSystem.setHierarchical(isHierarchial); + } metric.setActiveSubSystems(); } if (subsystem2 != null) { @@ -203,6 +209,11 @@ } + private static boolean getHierarchical(MemorySubSystem subsystem) { + long hierarchical = SubSystem.getLongValue(subsystem, "memory.use_hierarchy"); + return hierarchical > 0; + } + private void setActiveSubSystems() { activeSubSystems = true; } @@ -211,7 +222,7 @@ return activeSubSystems; } - private void setMemorySubSystem(SubSystem memory) { + private void setMemorySubSystem(MemorySubSystem memory) { this.memory = memory; } @@ -366,9 +377,29 @@ public long getMemoryLimit() { long retval = SubSystem.getLongValue(memory, "memory.limit_in_bytes"); + if (retval > unlimited_minimum) { + if (memory.isHierarchical()) { + // memory.limit_in_bytes returned unlimited, attempt + // hierarchical memory limit + String match = "hierarchical_memory_limit"; + retval = SubSystem.getLongValueMatchingLine(memory, + "memory.stat", + match, + Metrics::convertHierachicalLimitLine); + } + } return retval > unlimited_minimum ? -1L : retval; } + public static long convertHierachicalLimitLine(String line) { + String[] tokens = line.split("\\s"); + if (tokens.length == 2) { + String strVal = tokens[1]; + return SubSystem.convertStringToLong(strVal); + } + return unlimited_minimum + 1; // unlimited + } + public long getMemoryMaxUsage() { return SubSystem.getLongValue(memory, "memory.max_usage_in_bytes"); } @@ -417,6 +448,17 @@ public long getMemoryAndSwapLimit() { long retval = SubSystem.getLongValue(memory, "memory.memsw.limit_in_bytes"); + if (retval > unlimited_minimum) { + if (memory.isHierarchical()) { + // memory.memsw.limit_in_bytes returned unlimited, attempt + // hierarchical memory limit + String match = "hierarchical_memsw_limit"; + retval = SubSystem.getLongValueMatchingLine(memory, + "memory.stat", + match, + Metrics::convertHierachicalLimitLine); + } + } return retval > unlimited_minimum ? -1L : retval; } diff -Nru openjdk-13-13~17/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java openjdk-13-13~18/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java --- openjdk-13-13~17/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java 2019-04-24 19:25:41.000000000 +0000 @@ -29,10 +29,11 @@ import java.io.IOException; import java.math.BigInteger; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.function.Function; import java.util.stream.Stream; public class SubSystem { @@ -99,10 +100,32 @@ } + public static long getLongValueMatchingLine(SubSystem subsystem, + String param, + String match, + Function conversion) { + long retval = Metrics.unlimited_minimum + 1; // default unlimited + try { + List lines = Files.readAllLines(Paths.get(subsystem.path(), param)); + for (String line: lines) { + if (line.contains(match)) { + retval = conversion.apply(line); + break; + } + } + } catch (IOException e) { + // Ignore. Default is unlimited. + } + return retval; + } + public static long getLongValue(SubSystem subsystem, String parm) { String strval = getStringValue(subsystem, parm); - long retval = 0; + return convertStringToLong(strval); + } + public static long convertStringToLong(String strval) { + long retval = 0; if (strval == null) return 0L; try { @@ -215,4 +238,22 @@ return ints; } + + public static class MemorySubSystem extends SubSystem { + + private boolean hierarchical; + + public MemorySubSystem(String root, String mountPoint) { + super(root, mountPoint); + } + + boolean isHierarchical() { + return hierarchical; + } + + void setHierarchical(boolean hierarchical) { + this.hierarchical = hierarchical; + } + + } } diff -Nru openjdk-13-13~17/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java openjdk-13-13~18/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java --- openjdk-13-13~17/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java 2019-04-24 19:25:41.000000000 +0000 @@ -263,13 +263,13 @@ throw new InvalidKeyException("Unknown mode: " + opmode); } RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); - if (key instanceof RSAPublicKey) { + if (rsaKey instanceof RSAPublicKey) { mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY; - publicKey = (RSAPublicKey)key; + publicKey = (RSAPublicKey)rsaKey; privateKey = null; } else { // must be RSAPrivateKey per check in toRSAKey mode = encrypt ? MODE_SIGN : MODE_DECRYPT; - privateKey = (RSAPrivateKey)key; + privateKey = (RSAPrivateKey)rsaKey; publicKey = null; } int n = RSACore.getByteLength(rsaKey.getModulus()); diff -Nru openjdk-13-13~17/src/java.base/share/classes/java/lang/String.java openjdk-13-13~18/src/java.base/share/classes/java/lang/String.java --- openjdk-13-13~17/src/java.base/share/classes/java/lang/String.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.base/share/classes/java/lang/String.java 2019-04-24 19:25:41.000000000 +0000 @@ -1020,9 +1020,8 @@ } if (anObject instanceof String) { String aString = (String)anObject; - if (coder() == aString.coder()) { - return isLatin1() ? StringLatin1.equals(value, aString.value) - : StringUTF16.equals(value, aString.value); + if (!COMPACT_STRINGS || this.coder == aString.coder) { + return StringLatin1.equals(value, aString.value); } } return false; @@ -1057,7 +1056,8 @@ } byte v1[] = value; byte v2[] = sb.getValue(); - if (coder() == sb.getCoder()) { + byte coder = coder(); + if (coder == sb.getCoder()) { int n = v1.length; for (int i = 0; i < n; i++) { if (v1[i] != v2[i]) { @@ -1065,7 +1065,7 @@ } } } else { - if (!isLatin1()) { // utf16 str and latin1 abs can never be "equal" + if (coder != LATIN1) { // utf16 str and latin1 abs can never be "equal" return false; } return StringUTF16.contentEquals(v1, v2, len); @@ -1209,12 +1209,13 @@ public int compareTo(String anotherString) { byte v1[] = value; byte v2[] = anotherString.value; - if (coder() == anotherString.coder()) { - return isLatin1() ? StringLatin1.compareTo(v1, v2) - : StringUTF16.compareTo(v1, v2); + byte coder = coder(); + if (coder == anotherString.coder()) { + return coder == LATIN1 ? StringLatin1.compareTo(v1, v2) + : StringUTF16.compareTo(v1, v2); } - return isLatin1() ? StringLatin1.compareToUTF16(v1, v2) - : StringUTF16.compareToLatin1(v1, v2); + return coder == LATIN1 ? StringLatin1.compareToUTF16(v1, v2) + : StringUTF16.compareToLatin1(v1, v2); } /** @@ -1238,12 +1239,13 @@ public int compare(String s1, String s2) { byte v1[] = s1.value; byte v2[] = s2.value; - if (s1.coder() == s2.coder()) { - return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2) - : StringUTF16.compareToCI(v1, v2); + byte coder = s1.coder(); + if (coder == s2.coder()) { + return coder == LATIN1 ? StringLatin1.compareToCI(v1, v2) + : StringUTF16.compareToCI(v1, v2); } - return s1.isLatin1() ? StringLatin1.compareToCI_UTF16(v1, v2) - : StringUTF16.compareToCI_Latin1(v1, v2); + return coder == LATIN1 ? StringLatin1.compareToCI_UTF16(v1, v2) + : StringUTF16.compareToCI_Latin1(v1, v2); } /** Replaces the de-serialized object. */ @@ -1317,7 +1319,8 @@ (ooffset > (long)other.length() - len)) { return false; } - if (coder() == other.coder()) { + byte coder = coder(); + if (coder == other.coder()) { if (!isLatin1() && (len > 0)) { toffset = toffset << 1; ooffset = ooffset << 1; @@ -1329,7 +1332,7 @@ } } } else { - if (coder() == LATIN1) { + if (coder == LATIN1) { while (len-- > 0) { if (StringLatin1.getChar(tv, toffset++) != StringUTF16.getChar(ov, ooffset++)) { @@ -1411,12 +1414,13 @@ } byte tv[] = value; byte ov[] = other.value; - if (coder() == other.coder()) { - return isLatin1() + byte coder = coder(); + if (coder == other.coder()) { + return coder == LATIN1 ? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len) : StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len); } - return isLatin1() + return coder == LATIN1 ? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len) : StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len); } @@ -1447,15 +1451,16 @@ byte pa[] = prefix.value; int po = 0; int pc = pa.length; - if (coder() == prefix.coder()) { - int to = isLatin1() ? toffset : toffset << 1; + byte coder = coder(); + if (coder == prefix.coder()) { + int to = (coder == LATIN1) ? toffset : toffset << 1; while (po < pc) { if (ta[to++] != pa[po++]) { return false; } } } else { - if (isLatin1()) { // && pcoder == UTF16 + if (coder == LATIN1) { // && pcoder == UTF16 return false; } // coder == UTF16 && pcoder == LATIN1) @@ -1688,11 +1693,12 @@ * or {@code -1} if there is no such occurrence. */ public int indexOf(String str) { - if (coder() == str.coder()) { + byte coder = coder(); + if (coder == str.coder()) { return isLatin1() ? StringLatin1.indexOf(value, str.value) : StringUTF16.indexOf(value, str.value); } - if (coder() == LATIN1) { // str.coder == UTF16 + if (coder == LATIN1) { // str.coder == UTF16 return -1; } return StringUTF16.indexOfLatin1(value, str.value); diff -Nru openjdk-13-13~17/src/java.base/share/classes/java/time/chrono/JapaneseEra.java openjdk-13-13~18/src/java.base/share/classes/java/time/chrono/JapaneseEra.java --- openjdk-13-13~17/src/java.base/share/classes/java/time/chrono/JapaneseEra.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.base/share/classes/java/time/chrono/JapaneseEra.java 2019-04-24 19:25:41.000000000 +0000 @@ -154,6 +154,8 @@ * The singleton instance for the 'Reiwa' era (2019-05-01 - ) * which has the value 3. The end date of this era is not specified, unless * the Japanese Government defines it. + * + * @since 13 */ public static final JapaneseEra REIWA = new JapaneseEra(3, LocalDate.of(2019, 5, 1)); diff -Nru openjdk-13-13~17/src/java.base/share/native/include/classfile_constants.h.template openjdk-13-13~18/src/java.base/share/native/include/classfile_constants.h.template --- openjdk-13-13~17/src/java.base/share/native/include/classfile_constants.h.template 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.base/share/native/include/classfile_constants.h.template 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,7 +109,9 @@ JVM_CONSTANT_MethodType = 16, // JSR 292 JVM_CONSTANT_Dynamic = 17, JVM_CONSTANT_InvokeDynamic = 18, - JVM_CONSTANT_ExternalMax = 18 + JVM_CONSTANT_Module = 19, + JVM_CONSTANT_Package = 20, + JVM_CONSTANT_ExternalMax = 20 }; /* JVM_CONSTANT_MethodHandle subtypes */ diff -Nru openjdk-13-13~17/src/java.desktop/macosx/classes/sun/font/CFont.java openjdk-13-13~18/src/java.desktop/macosx/classes/sun/font/CFont.java --- openjdk-13-13~17/src/java.desktop/macosx/classes/sun/font/CFont.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/macosx/classes/sun/font/CFont.java 2019-04-24 19:25:41.000000000 +0000 @@ -78,17 +78,10 @@ } @Override - protected long getLayoutTableCache() { - return getLayoutTableCacheNative(getNativeFontPtr()); - } - - @Override protected byte[] getTableBytes(int tag) { return getTableBytesNative(getNativeFontPtr(), tag); } - private native synchronized long getLayoutTableCacheNative(long nativeFontPtr); - private native byte[] getTableBytesNative(long nativeFontPtr, int tag); private static native long createNativeFont(final String nativeFontName, diff -Nru openjdk-13-13~17/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.h openjdk-13-13~18/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.h --- openjdk-13-13~17/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.h 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.h 2019-04-24 19:25:41.000000000 +0000 @@ -26,8 +26,6 @@ #import #import -#import "fontscalerdefs.h" - #define MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE 256 @interface AWTFont : NSObject { @@ -35,7 +33,6 @@ NSFont *fFont; CGFontRef fNativeCGFont; BOOL fIsFakeItalic; - TTLayoutTableCache* layoutTableCache; } + (AWTFont *) awtFontForName:(NSString *)name diff -Nru openjdk-13-13~17/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m openjdk-13-13~18/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m --- openjdk-13-13~17/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m 2019-04-24 19:25:41.000000000 +0000 @@ -42,33 +42,10 @@ if (self) { fFont = [font retain]; fNativeCGFont = CTFontCopyGraphicsFont((CTFontRef)font, NULL); - layoutTableCache = NULL; } return self; } -static TTLayoutTableCache* newCFontLayoutTableCache() { - TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache)); - if (ltc) { - int i; - for(i=0;ientries[i].len = -1; - } - } - return ltc; -} - -static void freeCFontLayoutTableCache(TTLayoutTableCache* ltc) { - if (ltc) { - int i; - for(i=0;ientries[i].ptr) free (ltc->entries[i].ptr); - } - if (ltc->kernPairs) free(ltc->kernPairs); - free(ltc); - } -} - - (void) dealloc { [fFont release]; fFont = nil; @@ -76,10 +53,6 @@ if (fNativeCGFont) { CGFontRelease(fNativeCGFont); fNativeCGFont = NULL; - if (layoutTableCache != NULL) { - freeCFontLayoutTableCache(layoutTableCache); - layoutTableCache = NULL; - } } [super dealloc]; @@ -90,10 +63,6 @@ CGFontRelease(fNativeCGFont); fNativeCGFont = NULL; } - if (layoutTableCache != NULL) { - freeCFontLayoutTableCache(layoutTableCache); - layoutTableCache = NULL; - } [super finalize]; } @@ -432,23 +401,6 @@ } /* - * Class: sun_font_CFont - * Method: getLayoutTableCacheNative - * Signature: (J)J - */ -JNIEXPORT jlong JNICALL -Java_sun_font_CFont_getLayoutTableCacheNative - (JNIEnv *env, jclass clazz, - jlong awtFontPtr) -{ - AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr); - if (awtFont->layoutTableCache == NULL) { - awtFont->layoutTableCache = newCFontLayoutTableCache(); - } - return (jlong)(awtFont->layoutTableCache); -} - -/* * Class: sun_font_CFont * Method: getTableBytesNative * Signature: (JI)[B diff -Nru openjdk-13-13~17/src/java.desktop/share/classes/sun/font/Font2D.java openjdk-13-13~18/src/java.desktop/share/classes/sun/font/Font2D.java --- openjdk-13-13~17/src/java.desktop/share/classes/sun/font/Font2D.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/classes/sun/font/Font2D.java 2019-04-24 19:25:41.000000000 +0000 @@ -465,13 +465,6 @@ return null; } - /* implemented for fonts backed by an sfnt that has - * OpenType or AAT layout tables. - */ - protected long getLayoutTableCache() { - return 0L; - } - /* Used only on OS X. */ protected long getPlatformNativeFontPtr() { diff -Nru openjdk-13-13~17/src/java.desktop/share/classes/sun/font/FontScaler.java openjdk-13-13~18/src/java.desktop/share/classes/sun/font/FontScaler.java --- openjdk-13-13~17/src/java.desktop/share/classes/sun/font/FontScaler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/classes/sun/font/FontScaler.java 2019-04-24 19:25:41.000000000 +0000 @@ -181,25 +181,6 @@ abstract int getMissingGlyphCode() throws FontScalerException; abstract int getGlyphCode(char charCode) throws FontScalerException; - /* This method returns table cache used by native layout engine. - * This cache is essentially just small collection of - * pointers to various truetype tables. See definition of TTLayoutTableCache - * in the fontscalerdefs.h for more details. - * - * Note that tables themselves have same format as defined in the truetype - * specification, i.e. font scaler do not need to perform any preprocessing. - * - * Probably it is better to have API to request pointers to each table - * separately instead of requesting pointer to some native structure. - * (then there is not need to share its definition by different - * implementations of scaler). - * However, this means multiple JNI calls and potential impact on performance. - * - * Note: return value 0 is legal. - * This means tables are not available (e.g. type1 font). - */ - abstract long getLayoutTableCache() throws FontScalerException; - /* Used by the OpenType engine for mark positioning. */ abstract Point2D.Float getGlyphPoint(long pScalerContext, int glyphCode, int ptNumber) diff -Nru openjdk-13-13~17/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java openjdk-13-13~18/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java --- openjdk-13-13~17/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java 2019-04-24 19:25:41.000000000 +0000 @@ -163,10 +163,6 @@ .getNullScaler().getGlyphVectorOutline(0L, glyphs, numGlyphs, x, y); } - synchronized long getLayoutTableCache() throws FontScalerException { - return getLayoutTableCacheNative(nativeScaler); - } - public synchronized void dispose() { if (nativeScaler != 0L) { disposeNativeScaler(font.get(), nativeScaler); @@ -243,8 +239,6 @@ native Point2D.Float getGlyphPointNative(Font2D font, long pScalerContext, long pScaler, int glyphCode, int ptNumber); - private native long getLayoutTableCacheNative(long pScaler); - private native void disposeNativeScaler(Font2D font2D, long pScaler); private native int getGlyphCodeNative(Font2D font, long pScaler, char charCode); diff -Nru openjdk-13-13~17/src/java.desktop/share/classes/sun/font/NullFontScaler.java openjdk-13-13~18/src/java.desktop/share/classes/sun/font/NullFontScaler.java --- openjdk-13-13~17/src/java.desktop/share/classes/sun/font/NullFontScaler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/classes/sun/font/NullFontScaler.java 2019-04-24 19:25:41.000000000 +0000 @@ -64,8 +64,6 @@ return new GeneralPath(); } - long getLayoutTableCache() {return 0L;} - long createScalerContext(double[] matrix, int aa, int fm, float boldness, float italic, boolean disableHinting) { return getNullScalerContext(); diff -Nru openjdk-13-13~17/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java openjdk-13-13~18/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java --- openjdk-13-13~17/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java 2019-04-24 19:25:41.000000000 +0000 @@ -31,10 +31,12 @@ package sun.font; import sun.font.GlyphLayout.*; +import sun.java2d.Disposer; +import sun.java2d.DisposerRecord; + import java.awt.geom.Point2D; import java.lang.ref.SoftReference; import java.util.concurrent.ConcurrentHashMap; -import java.util.Locale; import java.util.WeakHashMap; /* @@ -150,8 +152,10 @@ } static WeakHashMap aatInfo = new WeakHashMap<>(); + private static final WeakHashMap facePtr = + new WeakHashMap<>(); - private boolean isAAT(Font2D font) { + private static boolean isAAT(Font2D font) { Boolean aatObj; synchronized (aatInfo) { aatObj = aatInfo.get(font); @@ -175,30 +179,67 @@ return aat; } + private long getFacePtr(Font2D font2D) { + FaceRef ref; + synchronized (facePtr) { + ref = facePtr.computeIfAbsent(font2D, FaceRef::new); + } + return ref.getNativePtr(); + } + public void layout(FontStrikeDesc desc, float[] mat, float ptSize, int gmask, int baseIndex, TextRecord tr, int typo_flags, Point2D.Float pt, GVData data) { Font2D font = key.font(); FontStrike strike = font.getStrike(desc); - long layoutTables = font.getLayoutTableCache(); long pNativeFont = font.getPlatformNativeFontPtr(); // used on OSX - // pScaler probably not needed long term. - long pScaler = 0L; - if (font instanceof FileFont) { - pScaler = ((FileFont)font).getScaler().nativeScaler; - } - shape(font, strike, ptSize, mat, pScaler, pNativeFont, - layoutTables, isAAT(font), - tr.text, data, key.script(), - tr.start, tr.limit, baseIndex, pt, - typo_flags, gmask); + long pFace = getFacePtr(font); + if (pFace != 0) { + shape(font, strike, ptSize, mat, pNativeFont, + pFace, isAAT(font), + tr.text, data, key.script(), + tr.start, tr.limit, baseIndex, pt, + typo_flags, gmask); + } } /* Native method to invoke harfbuzz layout engine */ private static native boolean shape(Font2D font, FontStrike strike, float ptSize, float[] mat, - long pscaler, long pNativeFont, long layoutTables, boolean aat, + long pNativeFont, long pFace, boolean aat, char[] chars, GVData data, int script, int offset, int limit, int baseIndex, Point2D.Float pt, int typo_flags, int slot); + + private static native long createFace(Font2D font, + boolean aat, + long platformNativeFontPtr); + + private static native void disposeFace(long facePtr); + + private static class FaceRef implements DisposerRecord { + private Font2D font; + private Long facePtr; + + private FaceRef(Font2D font) { + this.font = font; + } + + private synchronized long getNativePtr() { + if (facePtr == null) { + facePtr = createFace(font, isAAT(font), + font.getPlatformNativeFontPtr()); + if (facePtr != 0) { + Disposer.addObjectRecord(font, this); + } + font = null; + } + return facePtr; + } + + @Override + public void dispose() { + disposeFace(facePtr); + } + } } diff -Nru openjdk-13-13~17/src/java.desktop/share/classes/sun/font/TrueTypeFont.java openjdk-13-13~18/src/java.desktop/share/classes/sun/font/TrueTypeFont.java --- openjdk-13-13~17/src/java.desktop/share/classes/sun/font/TrueTypeFont.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/classes/sun/font/TrueTypeFont.java 2019-04-24 19:25:41.000000000 +0000 @@ -897,15 +897,6 @@ } @Override - protected long getLayoutTableCache() { - try { - return getScaler().getLayoutTableCache(); - } catch(FontScalerException fe) { - return 0L; - } - } - - @Override protected byte[] getTableBytes(int tag) { ByteBuffer buffer = getTableBuffer(tag); if (buffer == null) { diff -Nru openjdk-13-13~17/src/java.desktop/share/native/common/font/fontscalerdefs.h openjdk-13-13~18/src/java.desktop/share/native/common/font/fontscalerdefs.h --- openjdk-13-13~17/src/java.desktop/share/native/common/font/fontscalerdefs.h 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/native/common/font/fontscalerdefs.h 2019-04-24 19:25:41.000000000 +0000 @@ -88,32 +88,8 @@ */ #define INVISIBLE_GLYPHS 0xfffe -#define GSUB_TAG 0x47535542 /* 'GSUB' */ -#define GPOS_TAG 0x47504F53 /* 'GPOS' */ -#define GDEF_TAG 0x47444546 /* 'GDEF' */ -#define HEAD_TAG 0x68656164 /* 'head' */ -#define MORT_TAG 0x6D6F7274 /* 'mort' */ -#define MORX_TAG 0x6D6F7278 /* 'morx' */ -#define KERN_TAG 0x6B65726E /* 'kern' */ - -typedef struct TTLayoutTableCacheEntry { - const void* ptr; - int len; - int tag; -} TTLayoutTableCacheEntry; - -#define LAYOUTCACHE_ENTRIES 7 - -typedef struct TTLayoutTableCache { - TTLayoutTableCacheEntry entries[LAYOUTCACHE_ENTRIES]; - void* kernPairs; -} TTLayoutTableCache; - #include "sunfontids.h" -JNIEXPORT extern TTLayoutTableCache* newLayoutTableCache(); -JNIEXPORT extern void freeLayoutTableCache(TTLayoutTableCache* ltc); - /* If font is malformed then scaler context created by particular scaler * will be replaced by null scaler context. * Note that this context is not compatible with structure of the context diff -Nru openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/freetypeScaler.c openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/freetypeScaler.c --- openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/freetypeScaler.c 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/freetypeScaler.c 2019-04-24 19:25:41.000000000 +0000 @@ -69,7 +69,6 @@ unsigned fontDataOffset; unsigned fontDataLength; unsigned fileSize; - TTLayoutTableCache* layoutTables; } FTScalerInfo; typedef struct FTScalerContext { @@ -251,7 +250,6 @@ if (type == TYPE1_FROM_JAVA) { /* TYPE1 */ scalerInfo->fontData = (unsigned char*) malloc(filesize); scalerInfo->directBuffer = NULL; - scalerInfo->layoutTables = NULL; scalerInfo->fontDataLength = filesize; if (scalerInfo->fontData != NULL) { @@ -866,32 +864,6 @@ return ptr_to_jlong(glyphInfo); } - -/* - * Class: sun_font_FreetypeFontScaler - * Method: getLayoutTableCacheNative - * Signature: (J)J - */ -JNIEXPORT jlong JNICALL -Java_sun_font_FreetypeFontScaler_getLayoutTableCacheNative( - JNIEnv *env, jobject scaler, jlong pScaler) { - FTScalerInfo *scalerInfo = (FTScalerInfo*) jlong_to_ptr(pScaler); - - if (scalerInfo == NULL) { - invalidateJavaScaler(env, scaler, scalerInfo); - return 0L; - } - - // init layout table cache in font - // we're assuming the font is a file font and moreover it is Truetype font - // otherwise we shouldn't be able to get here... - if (scalerInfo->layoutTables == NULL) { - scalerInfo->layoutTables = newLayoutTableCache(); - } - - return ptr_to_jlong(scalerInfo->layoutTables); -} - /* * Class: sun_font_FreetypeFontScaler * Method: disposeNativeScaler diff -Nru openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc --- openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc 2019-04-24 19:25:41.000000000 +0000 @@ -23,6 +23,9 @@ * questions. */ +#include "jlong.h" +#include "sun_font_SunLayoutEngine.h" + #include "hb.h" #include "hb-jdk.h" #ifdef MACOSX @@ -304,79 +307,113 @@ static void _free_nothing(void*) { } +struct Font2DPtr { + JavaVM* vmPtr; + jweak font2DRef; +}; + +static void cleanupFontInfo(void* data) { + Font2DPtr* fontInfo; + JNIEnv* env; + + fontInfo = (Font2DPtr*) data; + fontInfo->vmPtr->GetEnv((void**)&env, JNI_VERSION_1_1); + env->DeleteWeakGlobalRef(fontInfo->font2DRef); + free(data); +} + static hb_blob_t * reference_table(hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) { - JDKFontInfo *jdkFontInfo = (JDKFontInfo*)user_data; - JNIEnv* env = jdkFontInfo->env; - jobject font2D = jdkFontInfo->font2D; - jsize length = 0; - void* buffer = NULL; - int cacheIdx = 0; + Font2DPtr *fontInfo; + JNIEnv* env; + jobject font2D; + jsize length; + void* buffer; // HB_TAG_NONE is 0 and is used to get the whole font file. // It is not expected to be needed for JDK. - if (tag == 0 || jdkFontInfo->layoutTables == NULL) { + if (tag == 0) { return NULL; } - for (cacheIdx=0; cacheIdxlayoutTables->entries[cacheIdx].tag) break; + fontInfo = (Font2DPtr*)user_data; + fontInfo->vmPtr->GetEnv((void**)&env, JNI_VERSION_1_1); + if (env == NULL) { + return NULL; } + font2D = fontInfo->font2DRef; - if (cacheIdx < LAYOUTCACHE_ENTRIES) { // if found - if (jdkFontInfo->layoutTables->entries[cacheIdx].len != -1) { - length = jdkFontInfo->layoutTables->entries[cacheIdx].len; - buffer = (void*)jdkFontInfo->layoutTables->entries[cacheIdx].ptr; - } - } - - if (buffer == NULL) { - jbyteArray tableBytes = (jbyteArray) - env->CallObjectMethod(font2D, sunFontIDs.getTableBytesMID, tag); - if (tableBytes == NULL) { - return NULL; - } - length = env->GetArrayLength(tableBytes); - buffer = calloc(length, sizeof(jbyte)); - env->GetByteArrayRegion(tableBytes, 0, length, (jbyte*)buffer); - - if (cacheIdx >= LAYOUTCACHE_ENTRIES) { // not a cacheable table - return hb_blob_create((const char *)buffer, length, - HB_MEMORY_MODE_WRITABLE, - buffer, free); - } else { - jdkFontInfo->layoutTables->entries[cacheIdx].len = length; - jdkFontInfo->layoutTables->entries[cacheIdx].ptr = buffer; - } + jbyteArray tableBytes = (jbyteArray) + env->CallObjectMethod(font2D, sunFontIDs.getTableBytesMID, tag); + if (tableBytes == NULL) { + return NULL; } + length = env->GetArrayLength(tableBytes); + buffer = calloc(length, sizeof(jbyte)); + env->GetByteArrayRegion(tableBytes, 0, length, (jbyte*)buffer); return hb_blob_create((const char *)buffer, length, - HB_MEMORY_MODE_READONLY, - NULL, _free_nothing); + HB_MEMORY_MODE_WRITABLE, + buffer, free); } +extern "C" { +/* + * Class: sun_font_SunLayoutEngine + * Method: createFace + * Signature: (Lsun/font/Font2D;ZJJ)J + */ +JNIEXPORT jlong JNICALL Java_sun_font_SunLayoutEngine_createFace(JNIEnv *env, + jclass cls, + jobject font2D, + jboolean aat, + jlong platformFontPtr) { +#ifdef MACOSX + if (aat && platformFontPtr) { + hb_face_t *face = hb_coretext_face_create((CGFontRef)platformFontPtr); + return ptr_to_jlong(face); + } +#endif + Font2DPtr *fi = (Font2DPtr*)malloc(sizeof(Font2DPtr)); + if (!fi) { + return 0; + } + JavaVM* vmPtr; + env->GetJavaVM(&vmPtr); + fi->vmPtr = vmPtr; + fi->font2DRef = env->NewWeakGlobalRef(font2D); + if (!fi->font2DRef) { + free(fi); + return 0; + } + hb_face_t *face = hb_face_create_for_tables(reference_table, fi, + cleanupFontInfo); + return ptr_to_jlong(face); +} -hb_face_t* -hb_jdk_face_create(JDKFontInfo *jdkFontInfo, - hb_destroy_func_t destroy) { - - hb_face_t *face = - hb_face_create_for_tables(reference_table, jdkFontInfo, destroy); - - return face; +/* + * Class: sun_font_SunLayoutEngine + * Method: disposeFace + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_font_SunLayoutEngine_disposeFace(JNIEnv *env, + jclass cls, + jlong ptr) { + hb_face_t* face = (hb_face_t*) jlong_to_ptr(ptr); + hb_face_destroy(face); } -static hb_font_t* _hb_jdk_font_create(JDKFontInfo *jdkFontInfo, +} // extern "C" + +static hb_font_t* _hb_jdk_font_create(hb_face_t* face, + JDKFontInfo *jdkFontInfo, hb_destroy_func_t destroy) { hb_font_t *font; - hb_face_t *face; - face = hb_jdk_face_create(jdkFontInfo, destroy); font = hb_font_create(face); - hb_face_destroy (face); hb_font_set_funcs (font, _hb_jdk_get_font_funcs (), jdkFontInfo, (hb_destroy_func_t) _do_nothing); @@ -387,17 +424,11 @@ } #ifdef MACOSX -static hb_font_t* _hb_jdk_ct_font_create(JDKFontInfo *jdkFontInfo) { +static hb_font_t* _hb_jdk_ct_font_create(hb_face_t* face, + JDKFontInfo *jdkFontInfo) { hb_font_t *font = NULL; - hb_face_t *face = NULL; - if (jdkFontInfo->nativeFont == 0) { - return NULL; - } - face = hb_coretext_face_create((CGFontRef)(jdkFontInfo->nativeFont)); font = hb_font_create(face); - hb_face_destroy(face); - hb_font_set_scale(font, HBFloatToFixed(jdkFontInfo->ptSize), HBFloatToFixed(jdkFontInfo->ptSize)); @@ -405,18 +436,13 @@ } #endif -hb_font_t* hb_jdk_font_create(JDKFontInfo *jdkFontInfo, +hb_font_t* hb_jdk_font_create(hb_face_t* hbFace, + JDKFontInfo *jdkFontInfo, hb_destroy_func_t destroy) { - - hb_font_t* font = NULL; - #ifdef MACOSX - if (jdkFontInfo->aat) { - font = _hb_jdk_ct_font_create(jdkFontInfo); + if (jdkFontInfo->aat && jdkFontInfo->nativeFont) { + return _hb_jdk_ct_font_create(hbFace, jdkFontInfo); } #endif - if (font == NULL) { - font = _hb_jdk_font_create(jdkFontInfo, destroy); - } - return font; + return _hb_jdk_font_create(hbFace, jdkFontInfo, destroy); } diff -Nru openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/hb-jdk.h openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/hb-jdk.h --- openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/hb-jdk.h 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/hb-jdk.h 2019-04-24 19:25:41.000000000 +0000 @@ -29,7 +29,6 @@ #include "hb.h" #include #include -#include # ifdef __cplusplus extern "C" { @@ -40,7 +39,6 @@ jobject font2D; jobject fontStrike; long nativeFont; - TTLayoutTableCache *layoutTables; float matrix[4]; float ptSize; float xPtSize; @@ -65,7 +63,8 @@ hb_jdk_face_create(JDKFontInfo* jdkFontInfo, hb_destroy_func_t destroy); hb_font_t * -hb_jdk_font_create(JDKFontInfo* jdkFontInfo, +hb_jdk_font_create(hb_face_t* hbFace, + JDKFontInfo* jdkFontInfo, hb_destroy_func_t destroy); diff -Nru openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/HBShaper.c openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/HBShaper.c --- openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/HBShaper.c 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/HBShaper.c 2019-04-24 19:25:41.000000000 +0000 @@ -201,9 +201,7 @@ jobject font2D, jobject fontStrike, jfloat ptSize, - jlong pScaler, jlong pNativeFont, - jlong layoutTables, jfloatArray matrix, jboolean aat) { @@ -216,7 +214,6 @@ fi->font2D = font2D; fi->fontStrike = fontStrike; fi->nativeFont = pNativeFont; - fi->layoutTables = (TTLayoutTableCache*)layoutTables; fi->aat = aat; (*env)->GetFloatArrayRegion(env, matrix, 0, 4, fi->matrix); fi->ptSize = ptSize; @@ -241,9 +238,8 @@ jobject fontStrike, jfloat ptSize, jfloatArray matrix, - jlong pScaler, jlong pNativeFont, - jlong layoutTables, + jlong pFace, jboolean aat, jcharArray text, jobject gvdata, @@ -256,6 +252,7 @@ jint slot) { hb_buffer_t *buffer; + hb_face_t* hbface; hb_font_t* hbfont; jchar *chars; jsize len; @@ -272,7 +269,7 @@ JDKFontInfo *jdkFontInfo = createJDKFontInfo(env, font2D, fontStrike, ptSize, - pScaler, pNativeFont, layoutTables, matrix, aat); + pNativeFont, matrix, aat); if (!jdkFontInfo) { return JNI_FALSE; } @@ -280,7 +277,8 @@ jdkFontInfo->font2D = font2D; jdkFontInfo->fontStrike = fontStrike; - hbfont = hb_jdk_font_create(jdkFontInfo, NULL); + hbface = (hb_face_t*) jlong_to_ptr(pFace); + hbfont = hb_jdk_font_create(hbface, jdkFontInfo, NULL); buffer = hb_buffer_create(); hb_buffer_set_script(buffer, getHBScriptCode(script)); diff -Nru openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/sunFont.c openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/sunFont.c --- openjdk-13-13~17/src/java.desktop/share/native/libfontmanager/sunFont.c 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.desktop/share/native/libfontmanager/sunFont.c 2019-04-24 19:25:41.000000000 +0000 @@ -344,32 +344,3 @@ (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); } - -JNIEXPORT TTLayoutTableCache* newLayoutTableCache() { - TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache)); - if (ltc) { - int i; - for(i=0;ientries[i].len = -1; - } - ltc->entries[0].tag = GDEF_TAG; - ltc->entries[1].tag = GPOS_TAG; - ltc->entries[2].tag = GSUB_TAG; - ltc->entries[3].tag = HEAD_TAG; - ltc->entries[4].tag = KERN_TAG; - ltc->entries[5].tag = MORT_TAG; - ltc->entries[6].tag = MORX_TAG; - } - return ltc; -} - -JNIEXPORT void freeLayoutTableCache(TTLayoutTableCache* ltc) { - if (ltc) { - int i; - for(i=0;ientries[i].ptr) free (ltc->entries[i].ptr); - } - if (ltc->kernPairs) free(ltc->kernPairs); - free(ltc); - } -} diff -Nru openjdk-13-13~17/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java openjdk-13-13~18/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java --- openjdk-13-13~17/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java 2019-04-24 19:25:41.000000000 +0000 @@ -178,7 +178,12 @@ ! (k.equalsIgnoreCase("Authorization") && k.equalsIgnoreCase("Proxy-Authorization")); } + private static final BiPredicate HOST_RESTRICTED = (k,v) -> !"host".equalsIgnoreCase(k); + public static final BiPredicate PROXY_TUNNEL_RESTRICTED(HttpClient client) { + return CONTEXT_RESTRICTED(client).and(HOST_RESTRICTED); + } + private static final Predicate IS_HOST = "host"::equalsIgnoreCase; private static final Predicate IS_PROXY_HEADER = (k) -> k != null && k.length() > 6 && "proxy-".equalsIgnoreCase(k.substring(0,6)); private static final Predicate NO_PROXY_HEADER = @@ -250,7 +255,8 @@ public static final BiPredicate PROXY_TUNNEL_FILTER = (s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_TUNNEL_DISABLED_SCHEMES, - IS_PROXY_HEADER); + // Allows Proxy-* and Host headers when establishing the tunnel. + IS_PROXY_HEADER.or(IS_HOST)); public static final BiPredicate PROXY_FILTER = (s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_DISABLED_SCHEMES, ALL_HEADERS); diff -Nru openjdk-13-13~17/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java openjdk-13-13~18/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java --- openjdk-13-13~17/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,7 +103,8 @@ HttpClient client = http1Exchange.client(); // Filter overridable headers from userHeaders - userHeaders = HttpHeaders.of(userHeaders.map(), Utils.CONTEXT_RESTRICTED(client)); + userHeaders = HttpHeaders.of(userHeaders.map(), + connection.contextRestricted(request, client)); final HttpHeaders uh = userHeaders; diff -Nru openjdk-13-13~17/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java openjdk-13-13~18/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java --- openjdk-13-13~17/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java 2019-04-24 19:25:41.000000000 +0000 @@ -285,6 +285,16 @@ } } + BiPredicate contextRestricted(HttpRequestImpl request, HttpClient client) { + if (!isTunnel() && request.isConnect()) { + // establishing a proxy tunnel + assert request.proxy() == null; + return Utils.PROXY_TUNNEL_RESTRICTED(client); + } else { + return Utils.CONTEXT_RESTRICTED(client); + } + } + // Composes a new immutable HttpHeaders that combines the // user and system header but only keeps those headers that // start with "proxy-" diff -Nru openjdk-13-13~17/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java openjdk-13-13~18/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java --- openjdk-13-13~17/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java 2019-04-24 19:25:41.000000000 +0000 @@ -424,7 +424,8 @@ private void printModifiers(Element e) { ElementKind kind = e.getKind(); if (kind == PARAMETER) { - printAnnotationsInline(e); + // Print annotation inline + writer.print(annotationsToString(e)); } else { printAnnotations(e); indent(); @@ -460,39 +461,32 @@ break; } - - for(Modifier m: modifiers) { - writer.print(m.toString() + " "); + if (!modifiers.isEmpty()) { + writer.print(modifiers.stream() + .map(Modifier::toString) + .collect(Collectors.joining(" ", "", " "))); } } private void printFormalTypeParameters(Parameterizable e, boolean pad) { List typeParams = e.getTypeParameters(); - if (typeParams.size() > 0) { - writer.print("<"); - - boolean first = true; - for(TypeParameterElement tpe: typeParams) { - if (!first) - writer.print(", "); - printAnnotationsInline(tpe); - writer.print(tpe.toString()); - first = false; - } - - writer.print(">"); + if (!typeParams.isEmpty()) { + writer.print(typeParams.stream() + .map(tpe -> annotationsToString(tpe) + tpe.toString()) + .collect(Collectors.joining(", ", "<", ">"))); if (pad) writer.print(" "); } } - private void printAnnotationsInline(Element e) { - List annots = e.getAnnotationMirrors(); - for(AnnotationMirror annotationMirror : annots) { - writer.print(annotationMirror); - writer.print(" "); - } + private String annotationsToString(Element e) { + List annotations = e.getAnnotationMirrors(); + return annotations.isEmpty() ? + "" : + annotations.stream() + .map(AnnotationMirror::toString) + .collect(Collectors.joining(" ", "", " ")); } private void printAnnotations(Element e) { @@ -569,17 +563,11 @@ if(kind != ANNOTATION_TYPE) { List interfaces = e.getInterfaces(); - if (interfaces.size() > 0) { - writer.print((kind.isClass() ? " implements" : " extends")); - - boolean first = true; - for(TypeMirror interf: interfaces) { - if (!first) - writer.print(","); - writer.print(" "); - writer.print(interf.toString()); - first = false; - } + if (!interfaces.isEmpty()) { + writer.print((kind.isClass() ? " implements " : " extends ")); + writer.print(interfaces.stream() + .map(TypeMirror::toString) + .collect(Collectors.joining(", "))); } } } diff -Nru openjdk-13-13~17/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java openjdk-13-13~18/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java --- openjdk-13-13~17/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java 2019-04-24 19:25:41.000000000 +0000 @@ -1137,20 +1137,79 @@ private static long nativeKeyWrapperKeyID = 0; private static CK_MECHANISM nativeKeyWrapperMechanism = null; + private static long nativeKeyWrapperRefCount = 0; + private static Session nativeKeyWrapperSession = null; private final P11Key p11Key; private final byte[] nativeKeyInfo; + private boolean wrapperKeyUsed; // destroyed and recreated when refCount toggles to 1 private long keyID; - private boolean isTokenObject; - // phantom reference notification clean up for session keys private SessionKeyRef ref; private int refCount; + private static void createNativeKeyWrapper(Token token) + throws PKCS11Exception { + assert(nativeKeyWrapperKeyID == 0); + assert(nativeKeyWrapperRefCount == 0); + assert(nativeKeyWrapperSession == null); + // Create a global wrapping/unwrapping key + CK_ATTRIBUTE[] wrappingAttributes = token.getAttributes(O_GENERATE, + CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY), + new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3)}); + Session s = null; + try { + s = token.getObjSession(); + nativeKeyWrapperKeyID = token.p11.C_GenerateKey( + s.id(), new CK_MECHANISM(CKM_AES_KEY_GEN), + wrappingAttributes); + nativeKeyWrapperSession = s; + nativeKeyWrapperSession.addObject(); + byte[] iv = new byte[16]; + JCAUtil.getSecureRandom().nextBytes(iv); + nativeKeyWrapperMechanism = new CK_MECHANISM(CKM_AES_CBC_PAD, iv); + } catch (PKCS11Exception e) { + // best effort + } finally { + token.releaseSession(s); + } + } + + private static void deleteNativeKeyWrapper() { + Token token = nativeKeyWrapperSession.token; + if (token.isValid()) { + Session s = null; + try { + s = token.getOpSession(); + token.p11.C_DestroyObject(s.id(), nativeKeyWrapperKeyID); + nativeKeyWrapperSession.removeObject(); + } catch (PKCS11Exception e) { + // best effort + } finally { + token.releaseSession(s); + } + } + nativeKeyWrapperKeyID = 0; + nativeKeyWrapperMechanism = null; + nativeKeyWrapperSession = null; + } + + static void decWrapperKeyRef() { + synchronized(NativeKeyHolder.class) { + assert(nativeKeyWrapperKeyID != 0); + assert(nativeKeyWrapperRefCount > 0); + nativeKeyWrapperRefCount--; + if (nativeKeyWrapperRefCount == 0) { + deleteNativeKeyWrapper(); + } + } + } + NativeKeyHolder(P11Key p11Key, long keyID, Session keySession, boolean extractKeyInfo, boolean isTokenObject) { this.p11Key = p11Key; @@ -1160,35 +1219,23 @@ if (isTokenObject) { this.ref = null; } else { - this.ref = new SessionKeyRef(p11Key, keyID, keySession); - // Try extracting key info, if any error, disable it Token token = p11Key.token; if (extractKeyInfo) { try { - if (p11Key.sensitive && nativeKeyWrapperKeyID == 0) { + if (p11Key.sensitive) { + // p11Key native key information has to be wrapped synchronized(NativeKeyHolder.class) { - // Create a global wrapping/unwrapping key - CK_ATTRIBUTE[] wrappingAttributes = token.getAttributes - (O_GENERATE, CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY), - new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3), - }); - Session wrappingSession = null; - try { - wrappingSession = token.getObjSession(); - nativeKeyWrapperKeyID = token.p11.C_GenerateKey - (wrappingSession.id(), - new CK_MECHANISM(CKM_AES_KEY_GEN), - wrappingAttributes); - byte[] iv = new byte[16]; - JCAUtil.getSecureRandom().nextBytes(iv); - nativeKeyWrapperMechanism = new CK_MECHANISM - (CKM_AES_CBC_PAD, iv); - } catch (PKCS11Exception e) { - // best effort - } finally { - token.releaseSession(wrappingSession); + if (nativeKeyWrapperKeyID == 0) { + createNativeKeyWrapper(token); + } + // If a wrapper-key was successfully created or + // already exists, increment its reference + // counter to keep it alive while native key + // information is being held. + if (nativeKeyWrapperKeyID != 0) { + nativeKeyWrapperRefCount++; + wrapperKeyUsed = true; } } } @@ -1196,7 +1243,8 @@ try { opSession = token.getOpSession(); ki = p11Key.token.p11.getNativeKeyInfo(opSession.id(), - keyID, nativeKeyWrapperKeyID, nativeKeyWrapperMechanism); + keyID, nativeKeyWrapperKeyID, + nativeKeyWrapperMechanism); } catch (PKCS11Exception e) { // best effort } finally { @@ -1206,6 +1254,8 @@ // best effort } } + this.ref = new SessionKeyRef(p11Key, keyID, wrapperKeyUsed, + keySession); } this.nativeKeyInfo = ((ki == null || ki.length == 0)? null : ki); } @@ -1222,18 +1272,15 @@ throw new RuntimeException( "Error: null keyID with non-zero refCount " + cnt); } - if (this.ref != null) { - throw new RuntimeException( - "Error: null keyID with non-null session ref"); - } Token token = p11Key.token; // Create keyID using nativeKeyInfo Session session = null; try { session = token.getObjSession(); this.keyID = token.p11.createNativeKey(session.id(), - nativeKeyInfo, nativeKeyWrapperKeyID, nativeKeyWrapperMechanism); - this.ref = new SessionKeyRef(p11Key, this.keyID, session); + nativeKeyInfo, nativeKeyWrapperKeyID, + nativeKeyWrapperMechanism); + this.ref.registerNativeKey(this.keyID, session); } catch (PKCS11Exception e) { this.refCount--; throw new ProviderException("Error recreating native key", e); @@ -1263,12 +1310,9 @@ throw new RuntimeException("ERROR: null keyID can't be destroyed"); } - if (this.ref == null) { - throw new RuntimeException("ERROR: null session ref can't be disposed"); - } // destroy this.keyID = 0; - this.ref = this.ref.dispose(); + this.ref.removeNativeKey(); } else { if (cnt < 0) { // should never happen as we start count at 1 and pair get/release calls @@ -1285,12 +1329,11 @@ * otherwise the key maybe cleared before other objects which * still use these keys during finalization such as SSLSocket. */ -final class SessionKeyRef extends PhantomReference - implements Comparable { +final class SessionKeyRef extends PhantomReference { private static ReferenceQueue refQueue = new ReferenceQueue(); - private static Set refList = - Collections.synchronizedSortedSet(new TreeSet()); + private static Set refSet = + Collections.synchronizedSet(new HashSet()); static ReferenceQueue referenceQueue() { return refQueue; @@ -1307,47 +1350,69 @@ } // handle to the native key and the session it is generated under - private final long keyID; - private final Session session; + private long keyID; + private Session session; + private boolean wrapperKeyUsed; - SessionKeyRef(P11Key p11Key, long keyID, Session session) { + SessionKeyRef(P11Key p11Key, long keyID, boolean wrapperKeyUsed, + Session session) { super(p11Key, refQueue); if (session == null) { throw new ProviderException("key must be associated with a session"); } - this.keyID = keyID; - this.session = session; - this.session.addObject(); + registerNativeKey(keyID, session); + this.wrapperKeyUsed = wrapperKeyUsed; - refList.add(this); + refSet.add(this); drainRefQueueBounded(); } - SessionKeyRef dispose() { - Token token = session.token; - // If the token is still valid, try to remove the key object - if (token.isValid()) { - Session s = null; - try { - s = token.getOpSession(); - token.p11.C_DestroyObject(s.id(), keyID); - } catch (PKCS11Exception e) { - // best effort - } finally { - token.releaseSession(s); + void registerNativeKey(long newKeyID, Session newSession) { + assert(newKeyID != 0); + assert(newSession != null); + updateNativeKey(newKeyID, newSession); + } + + void removeNativeKey() { + assert(session != null); + updateNativeKey(0, null); + } + + private void updateNativeKey(long newKeyID, Session newSession) { + if (newKeyID == 0) { + assert(newSession == null); + Token token = session.token; + // If the token is still valid, try to remove the key object + if (token.isValid()) { + Session s = null; + try { + s = token.getOpSession(); + token.p11.C_DestroyObject(s.id(), this.keyID); + } catch (PKCS11Exception e) { + // best effort + } finally { + token.releaseSession(s); + } } + session.removeObject(); + } else { + newSession.addObject(); } - refList.remove(this); - this.clear(); - session.removeObject(); - return null; + keyID = newKeyID; + session = newSession; } - public int compareTo(SessionKeyRef other) { - if (this.keyID == other.keyID) { - return 0; - } else { - return (this.keyID < other.keyID) ? -1 : 1; + // Called when the GC disposes a p11Key + void dispose() { + if (wrapperKeyUsed) { + // Wrapper-key no longer needed for + // p11Key native key information + NativeKeyHolder.decWrapperKeyRef(); + } + if (keyID != 0) { + removeNativeKey(); } + refSet.remove(this); + this.clear(); } } diff -Nru openjdk-13-13~17/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c openjdk-13-13~18/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c --- openjdk-13-13~17/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c 2019-04-24 19:25:41.000000000 +0000 @@ -308,7 +308,7 @@ *(CK_BBOOL*)(((CK_ATTRIBUTE_PTR)(((CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes) +sensitiveAttributePosition))->pValue) == CK_TRUE) { // Key is sensitive. Need to extract it wrapped. - if (jWrappingKeyHandle != -1) { + if (jWrappingKeyHandle != 0) { jMechanismToCKMechanism(env, jWrappingMech, &ckMechanism); rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, &ckMechanism, @@ -351,6 +351,7 @@ goto cleanup; } } else { + ckAssertReturnValueOK(env, CKR_KEY_HANDLE_INVALID); goto cleanup; } returnValue = nativeKeyInfoWrappedKeyArray; diff -Nru openjdk-13-13~17/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java openjdk-13-13~18/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java --- openjdk-13-13~17/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,8 @@ public static final int JVM_CONSTANT_MethodType = 16; public static final int JVM_CONSTANT_Dynamic = 17; public static final int JVM_CONSTANT_InvokeDynamic = 18; + public static final int JVM_CONSTANT_Module = 19; + public static final int JVM_CONSTANT_Package = 20; // JVM_CONSTANT_MethodHandle subtypes public static final int JVM_REF_getField = 1; diff -Nru openjdk-13-13~17/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java openjdk-13-13~18/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java --- openjdk-13-13~17/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ ownerFieldOffset = f.getOffset(); f = type.getField("FreeNext"); FreeNextFieldOffset = f.getOffset(); - countField = type.getJIntField("_count"); + contentionsField = type.getJIntField("_contentions"); waitersField = type.getJIntField("_waiters"); recursionsField = type.getCIntegerField("_recursions"); } @@ -87,19 +87,14 @@ // FIXME // void set_queue(void* owner); - public int count() { return countField.getValue(addr); } - // FIXME - // void set_count(int count); - public long recursions() { return recursionsField.getValue(addr); } public OopHandle object() { return addr.getOopHandleAt(objectFieldOffset); } - // contentions is always equal to count public int contentions() { - return count(); + return contentionsField.getValue(addr); } // FIXME @@ -114,7 +109,7 @@ private static long objectFieldOffset; private static long ownerFieldOffset; private static long FreeNextFieldOffset; - private static JIntField countField; + private static JIntField contentionsField; private static JIntField waitersField; private static CIntegerField recursionsField; // FIXME: expose platform-dependent stuff diff -Nru openjdk-13-13~17/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java openjdk-13-13~18/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java --- openjdk-13-13~17/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,7 @@ } } } - tty.println(" _count: " + mon.count()); + tty.println(" _contentions: " + mon.contentions()); tty.println(" _waiters: " + mon.waiters()); tty.println(" _recursions: " + mon.recursions()); } @@ -98,7 +98,7 @@ ObjectMonitor mon; while (i.hasNext()) { mon = (ObjectMonitor)i.next(); - if (mon.count() != 0 || mon.waiters() != 0 || mon.owner() != null) { + if (mon.contentions() != 0 || mon.waiters() != 0 || mon.owner() != null) { OopHandle object = mon.object(); if (object == null) { dumpMonitor(tty, mon, true); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java 2019-04-24 19:25:41.000000000 +0000 @@ -22,11 +22,11 @@ */ /* @ApiInfo( - group="Graal SDK" + group="GraalVM SDK" ) */ /** - * The Graal-SDK collections package contains memory efficient data structures. + * The GraalVM SDK collections package contains memory efficient data structures. * * @see jdk.internal.vm.compiler.collections.EconomicMap * @see jdk.internal.vm.compiler.collections.EconomicSet diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraal.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraal.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraal.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraal.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package jdk.internal.vm.compiler.libgraal; + +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.services.Services; + +/** + * JDK13+ version of {@code LibGraal}. + */ +public class LibGraal { + + public static boolean isAvailable() { + return isCurrentRuntime() || libgraalIsolate != 0L; + } + + public static boolean isCurrentRuntime() { + return Services.IS_IN_NATIVE_IMAGE; + } + + public static long getIsolate() { + if (isCurrentRuntime() || !isAvailable()) { + throw new IllegalStateException(); + } + return libgraalIsolate; + } + + public static long getIsolateThread() { + if (isCurrentRuntime()) { + throw new IllegalStateException(); + } + return CURRENT_ISOLATE_THREAD.get(); + } + + @SuppressWarnings("unused") + public static long[] registerNativeMethods(HotSpotJVMCIRuntime runtime, Class clazz) { + if (clazz.isPrimitive()) { + throw new IllegalArgumentException(); + } + if (isCurrentRuntime() || !isAvailable()) { + throw new IllegalStateException(); + } + // Waiting for https://bugs.openjdk.java.net/browse/JDK-8220623 + // return runtime.registerNativeMethods(clazz); + throw new IllegalStateException("Requires JDK-8220623"); + } + + @SuppressWarnings("unused") + public static long translate(HotSpotJVMCIRuntime runtime, Object obj) { + if (!isAvailable()) { + throw new IllegalStateException(); + } + // return runtime.translate(obj); + throw new IllegalStateException("Requires JDK-8220623"); + } + + @SuppressWarnings("unused") + public static T unhand(HotSpotJVMCIRuntime runtime, Class type, long handle) { + if (!isAvailable()) { + throw new IllegalStateException(); + } + // return runtime.unhand(type, handle); + throw new IllegalStateException("Requires JDK-8220623"); + } + + private static final ThreadLocal CURRENT_ISOLATE_THREAD = new ThreadLocal<>() { + @Override + protected Long initialValue() { + return attachThread(libgraalIsolate); + } + }; + + private static final long libgraalIsolate = Services.IS_BUILDING_NATIVE_IMAGE ? 0L : initializeLibgraal(); + + private static long initializeLibgraal() { + try { + // Initialize JVMCI to ensure JVMCI opens its packages to + // Graal otherwise the call to HotSpotJVMCIRuntime.runtime() + // below will fail on JDK13+. + Services.initializeJVMCI(); + + // Waiting for https://bugs.openjdk.java.net/browse/JDK-8220623 + // HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); + // long[] nativeInterface = runtime.registerNativeMethods(LibGraal.class); + // return nativeInterface[1]; + return 0L; + } catch (UnsupportedOperationException e) { + return 0L; + } + } + + /** + * Attaches the current thread to a thread in {@code isolate}. + * + * @param isolate + */ + private static native long attachThread(long isolate); +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package jdk.internal.vm.compiler.libgraal; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Facilities for encoding/decoding a set of options to/from a byte array. + */ +public final class OptionsEncoder { + + private OptionsEncoder() { + } + + /** + * Determines if {@code value} is supported by {@link #encode(Map)}. + */ + public static boolean isValueSupported(Object value) { + if (value == null) { + return false; + } + Class valueClass = value.getClass(); + return valueClass == Boolean.class || + valueClass == Byte.class || + valueClass == Short.class || + valueClass == Character.class || + valueClass == Integer.class || + valueClass == Long.class || + valueClass == Float.class || + valueClass == Double.class || + valueClass == String.class || + value.getClass().isEnum(); + } + + /** + * Encodes {@code options} into a byte array. + * + * @throws IllegalArgumentException if any value in {@code options} is not + * {@linkplain #isValueSupported(Object) supported} + */ + public static byte[] encode(final Map options) { + try (ByteArrayOutputStream baout = new ByteArrayOutputStream()) { + try (DataOutputStream out = new DataOutputStream(baout)) { + out.writeInt(options.size()); + for (Map.Entry e : options.entrySet()) { + final String key = e.getKey(); + out.writeUTF(key); + final Object value = e.getValue(); + final Class valueClz = value.getClass(); + if (valueClz == Boolean.class) { + out.writeByte('Z'); + out.writeBoolean((Boolean) value); + } else if (valueClz == Byte.class) { + out.writeByte('B'); + out.writeByte((Byte) value); + } else if (valueClz == Short.class) { + out.writeByte('S'); + out.writeShort((Short) value); + } else if (valueClz == Character.class) { + out.writeByte('C'); + out.writeChar((Character) value); + } else if (valueClz == Integer.class) { + out.writeByte('I'); + out.writeInt((Integer) value); + } else if (valueClz == Long.class) { + out.writeByte('J'); + out.writeLong((Long) value); + } else if (valueClz == Float.class) { + out.writeByte('F'); + out.writeFloat((Float) value); + } else if (valueClz == Double.class) { + out.writeByte('D'); + out.writeDouble((Double) value); + } else if (valueClz == String.class) { + out.writeByte('U'); + out.writeUTF((String) value); + } else if (valueClz.isEnum()) { + out.writeByte('U'); + out.writeUTF(((Enum) value).name()); + } else { + throw new IllegalArgumentException(String.format("Key: %s, Value: %s, Value type: %s", key, value, valueClz)); + } + } + } + return baout.toByteArray(); + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); + } + } + + /** + * Decodes {@code input} into a name/value map. + * + * @throws IllegalArgumentException if {@code input} cannot be decoded + */ + public static Map decode(byte[] input) { + Map res = new HashMap<>(); + try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(input))) { + final int size = in.readInt(); + for (int i = 0; i < size; i++) { + final String key = in.readUTF(); + final Object value; + final byte type = in.readByte(); + switch (type) { + case 'Z': + value = in.readBoolean(); + break; + case 'B': + value = in.readByte(); + break; + case 'S': + value = in.readShort(); + break; + case 'C': + value = in.readChar(); + break; + case 'I': + value = in.readInt(); + break; + case 'J': + value = in.readLong(); + break; + case 'F': + value = in.readFloat(); + break; + case 'D': + value = in.readDouble(); + break; + case 'U': + value = in.readUTF(); + break; + default: + throw new IllegalArgumentException("Unsupported value type: " + Integer.toHexString(type)); + } + res.put(key, value); + } + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); + } + return res; + } +} + diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java 2019-04-24 19:25:41.000000000 +0000 @@ -22,7 +22,7 @@ */ /* @ApiInfo( - group="Graal SDK" + group="GraalVM SDK" ) */ /** diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java 2019-04-24 19:25:41.000000000 +0000 @@ -54,6 +54,11 @@ private List jumpDisplacementHints; /** + * Labels with instructions to be patched when it is {@linkplain Label#bind bound}. + */ + Label labelsWithPatches; + + /** * Backing code buffer. */ private final Buffer codeBuffer; @@ -151,13 +156,26 @@ * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true} */ public byte[] close(boolean trimmedCopy) { + checkAndClearLabelsWithPatches(); return codeBuffer.close(trimmedCopy); } + private void checkAndClearLabelsWithPatches() throws InternalError { + Label label = labelsWithPatches; + while (label != null) { + if (label.patchPositions != null) { + throw new InternalError("Label used by instructions at following offsets has not been bound: " + label.patchPositions); + } + Label next = label.nextWithPatches; + label.nextWithPatches = null; + label = next; + } + labelsWithPatches = null; + } + public void bind(Label l) { assert !l.isBound() : "can bind label only once"; - l.bind(position()); - l.patchInstructions(this); + l.bind(position(), this); } public abstract void align(int modulus); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Label.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Label.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Label.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Label.java 2019-04-24 19:25:41.000000000 +0000 @@ -35,10 +35,15 @@ private int blockId = -1; /** - * References to instructions that jump to this unresolved label. These instructions need to be - * patched when the label is bound using the {@link #patchInstructions(Assembler)} method. + * Positions of instructions that jump to this unresolved label. These instructions are patched + * when the label is bound. */ - private ArrayList patchPositions = null; + ArrayList patchPositions; + + /** + * Link in list of labels with instructions to be patched. + */ + Label nextWithPatches; /** * Returns the position of this label in the code buffer. @@ -62,36 +67,33 @@ } /** - * Binds the label to the specified position. - * - * @param pos the position + * Binds the label to {@code pos} and patches all instructions added by + * {@link #addPatchAt(int, Assembler)}. */ - protected void bind(int pos) { + protected void bind(int pos, Assembler asm) { + assert pos >= 0; this.position = pos; - assert isBound(); + if (patchPositions != null) { + for (int i = 0; i < patchPositions.size(); ++i) { + asm.patchJumpTarget(patchPositions.get(i), position); + } + patchPositions = null; + } } public boolean isBound() { return position >= 0; } - public void addPatchAt(int branchLocation) { + public void addPatchAt(int branchLocation, Assembler asm) { assert !isBound() : "Label is already bound " + this + " " + branchLocation + " at position " + position; if (patchPositions == null) { patchPositions = new ArrayList<>(2); + nextWithPatches = asm.labelsWithPatches; + asm.labelsWithPatches = this; } patchPositions.add(branchLocation); - } - protected void patchInstructions(Assembler masm) { - assert isBound() : "Label should be bound"; - if (patchPositions != null) { - int target = position; - for (int i = 0; i < patchPositions.size(); ++i) { - int pos = patchPositions.get(i); - masm.patchJumpTarget(pos, target); - } - } } public void reset() { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -25,9 +25,15 @@ package org.graalvm.compiler.asm.aarch64; +import static jdk.vm.ci.aarch64.AArch64.CPU; +import static jdk.vm.ci.aarch64.AArch64.SIMD; import static jdk.vm.ci.aarch64.AArch64.cpuRegisters; +import static jdk.vm.ci.aarch64.AArch64.r0; +import static jdk.vm.ci.aarch64.AArch64.sp; +import static jdk.vm.ci.aarch64.AArch64.zr; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADD; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDS; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDV; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADR; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADRP; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.AND; @@ -44,6 +50,7 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLREX; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLS; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLZ; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CNT; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSEL; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSINC; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSNEG; @@ -107,27 +114,24 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUB; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUBS; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SWP; -import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBZ; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBNZ; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBZ; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UBFM; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UDIV; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UMOV; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.FP32; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.FP64; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.General32; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.General64; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.floatFromSize; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.generalFromSize; -import static jdk.vm.ci.aarch64.AArch64.CPU; -import static jdk.vm.ci.aarch64.AArch64.SIMD; -import static jdk.vm.ci.aarch64.AArch64.r0; -import static jdk.vm.ci.aarch64.AArch64.sp; -import static jdk.vm.ci.aarch64.AArch64.zr; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.simdFromSize; import java.util.Arrays; import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.aarch64.AArch64; @@ -371,15 +375,41 @@ } /** + * Enumeration of all different lane types of SIMD register. + * + * Byte(B):8b/lane; HalfWord(H):16b/lane; Word(S):32b/lane; DoubleWord(D):64b/lane. + */ + public enum SIMDElementSize { + Byte(0, 8), + HalfWord(1, 16), + Word(2, 32), + DoubleWord(3, 64); + + public final int encoding; + public final int nbits; + + SIMDElementSize(int encoding, int nbits) { + this.encoding = encoding; + this.nbits = nbits; + } + } + + /** * Enumeration of all different instruction kinds: General32/64 are the general instructions * (integer, branch, etc.), for 32-, respectively 64-bit operands. FP32/64 is the encoding for - * the 32/64bit float operations + * the 32/64bit float operations. SIMDByte/HalfWord/Word/DoubleWord is the encoding for SIMD + * instructions */ protected enum InstructionType { General32(0b00 << 30, 32, true), General64(0b10 << 30, 64, true), FP32(0x00000000, 32, false), - FP64(0x00400000, 64, false); + FP64(0x00400000, 64, false), + + SIMDByte(0x01, 8, false), + SIMDHalfWord(0x02, 16, false), + SIMDWord(0x04, 32, false), + SIMDDoubleWord(0x08, 64, false); public final int encoding; public final int width; @@ -401,6 +431,20 @@ return size == 32 ? FP32 : FP64; } + public static InstructionType simdFromSize(int size) { + switch (size) { + case 8: + return SIMDByte; + case 16: + return SIMDHalfWord; + case 32: + return SIMDWord; + case 64: + return SIMDDoubleWord; + default: + throw GraalError.shouldNotReachHere(); + } + } } private static final int ImmediateOffset = 10; @@ -493,6 +537,10 @@ private static final int LDADDAcquireOffset = 23; private static final int LDADDReleaseOffset = 22; + private static final int SIMDImm5Offset = 16; + private static final int SIMDQBitOffset = 30; + private static final int SIMDSizeOffset = 22; + /** * Encoding for all instructions. */ @@ -611,7 +659,7 @@ FCSEL(0x1E200C00), INS(0x4e081c00), - UMOV(0x4e083c00), + UMOV(0x0e003c00), CNT(0xe205800), USRA(0x6f001400), @@ -626,7 +674,9 @@ MRS(0xD5300000), MSR(0xD5100000), - BLR_NATIVE(0xc0000000); + BLR_NATIVE(0xc0000000), + + ADDV(0x0e31b800); public final int encoding; @@ -2957,4 +3007,45 @@ } } + /** + * dst[0...n] = countBitCountOfEachByte(src[0...n]), n = size/8. + * + * @param size register size. Has to be 64 or 128. + * @param dst SIMD register. Should not be null. + * @param src SIMD register. Should not be null. + */ + public void cnt(int size, Register dst, Register src) { + assert 64 == size || 128 == size : "Invalid size for cnt"; + emitInt((size >> 7) << SIMDQBitOffset | CNT.encoding | rd(dst) | rs1(src)); + } + + /** + * dst = src[0] + ....+ src[n]. + * + * @param size register size. Has to be 64 or 128. + * @param laneWidth the width that SIMD register is treated as different lanes with. + * @param dst SIMD register. Should not be null. + * @param src SIMD register. Should not be null. + */ + public void addv(int size, SIMDElementSize laneWidth, Register dst, Register src) { + assert 64 == size || 128 == size : "Invalid size for addv"; + assert SIMDElementSize.DoubleWord != laneWidth : "Invalid lane width for addv"; + assert 64 != size || SIMDElementSize.Word != laneWidth : "Invalid size and lane combination for addv"; + emitInt((size >> 7) << SIMDQBitOffset | laneWidth.encoding << SIMDSizeOffset | ADDV.encoding | rd(dst) | rs1(src)); + } + + /** + * dst = src[srcIdx]. + * + * @param size register size. Can be 8, 16, 32 or 64. + * @param dst general purpose register. Should not be null or zero-register. + * @param srcIdx lane index of source register that dest data is from. + * @param src SIMD register. Should not be null. + */ + public void umov(int size, Register dst, int srcIdx, Register src) { + assert (srcIdx + 1) * size <= 128 : "Invalid src vectRegister index"; + InstructionType simdDataType = simdFromSize(size); + int imm5 = simdDataType.encoding | srcIdx << Integer.numberOfTrailingZeros(simdDataType.encoding) + 1; + emitInt((size >> 6) << SIMDQBitOffset | imm5 << SIMDImm5Offset | UMOV.encoding | rd(dst) | rs1(src)); + } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1437,7 +1437,7 @@ int offset = label.position() - position(); super.adr(dst, offset); } else { - label.addPatchAt(position()); + label.addPatchAt(position(), this); // Encode condition flag so that we know how to patch the instruction later emitInt(PatchLabelKind.ADR.encoding | dst.encoding << PatchLabelKind.INFORMATION_OFFSET); } @@ -1456,7 +1456,7 @@ int offset = label.position() - position(); super.cbnz(size, cmp, offset); } else { - label.addPatchAt(position()); + label.addPatchAt(position(), this); int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 1); int sizeEncoding = (size == 64 ? 1 : 0) << PatchLabelKind.INFORMATION_OFFSET; // Encode condition flag so that we know how to patch the instruction later @@ -1477,7 +1477,7 @@ int offset = label.position() - position(); super.cbz(size, cmp, offset); } else { - label.addPatchAt(position()); + label.addPatchAt(position(), this); int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 1); int sizeEncoding = (size == 64 ? 1 : 0) << PatchLabelKind.INFORMATION_OFFSET; // Encode condition flag so that we know how to patch the instruction later @@ -1498,7 +1498,7 @@ int offset = label.position() - position(); super.tbnz(cmp, uimm6, offset); } else { - label.addPatchAt(position()); + label.addPatchAt(position(), this); int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); emitInt(PatchLabelKind.BRANCH_BIT_NONZERO.encoding | indexEncoding | regEncoding); @@ -1518,7 +1518,7 @@ int offset = label.position() - position(); super.tbz(cmp, uimm6, offset); } else { - label.addPatchAt(position()); + label.addPatchAt(position(), this); int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); emitInt(PatchLabelKind.BRANCH_BIT_ZERO.encoding | indexEncoding | regEncoding); @@ -1537,7 +1537,7 @@ int offset = label.position() - position(); super.b(condition, offset); } else { - label.addPatchAt(position()); + label.addPatchAt(position(), this); // Encode condition flag so that we know how to patch the instruction later emitInt(PatchLabelKind.BRANCH_CONDITIONALLY.encoding | condition.encoding << PatchLabelKind.INFORMATION_OFFSET); } @@ -1565,7 +1565,7 @@ int offset = label.position() - position(); super.b(offset); } else { - label.addPatchAt(position()); + label.addPatchAt(position(), this); emitInt(PatchLabelKind.BRANCH_UNCONDITIONALLY.encoding); } } @@ -1783,6 +1783,23 @@ a.lea(this, d); } + /** + * Count the set bits of src register. + * + * @param size src register size. Has to be 32 or 64. + * @param dst general purpose register. Should not be null or zero-register. + * @param src general purpose register. Should not be null. + * @param vreg SIMD register. Should not be null. + */ + public void popcnt(int size, Register dst, Register src, Register vreg) { + assert 32 == size || 64 == size : "Invalid data size"; + fmov(size, vreg, src); + final int fixedSize = 64; + cnt(fixedSize, vreg, vreg); + addv(fixedSize, SIMDElementSize.Byte, vreg, vreg); + umov(fixedSize, dst, 0, vreg); + } + public interface MacroInstruction { void patch(int codePos, int relative, byte[] code); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64BitCountAssemblerTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64BitCountAssemblerTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64BitCountAssemblerTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64BitCountAssemblerTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Arm Limited. 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. + */ + + +package org.graalvm.compiler.asm.aarch64.test; + +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.junit.Assume.assumeTrue; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.asm.test.AssemblerTest; +import org.graalvm.compiler.code.CompilationResult; +import org.junit.Before; +import org.junit.Test; + +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterArray; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.JavaKind; + +public class AArch64BitCountAssemblerTest extends AssemblerTest { + @Before + public void checkAArch64() { + assumeTrue("skipping non AArch64 specific test", codeCache.getTarget().arch instanceof AArch64); + } + + public interface AArch64CodeGenTestCase { + CodeGenTest create(); + + int getExpected(); + } + + private class AArch64BitCountCodeGenTestCase implements AArch64CodeGenTestCase { + final T value; + final int size; + + AArch64BitCountCodeGenTestCase(T x, int size) { + assert x instanceof Integer || x instanceof Long; + this.value = x; + this.size = size; + } + + T getValue() { + return value; + } + + @Override + public CodeGenTest create() { + return (CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) -> { + AArch64MacroAssembler masm = new AArch64MacroAssembler(target); + Register dst = registerConfig.getReturnRegister(JavaKind.Int); + Register src = asRegister(cc.getArgument(0)); + RegisterArray registers = registerConfig.filterAllocatableRegisters(AArch64Kind.V64_BYTE, registerConfig.getAllocatableRegisters()); + masm.popcnt(size, dst, src, registers.get(registers.size() - 1)); + masm.ret(AArch64.lr); + return masm.close(true); + }; + } + + @Override + public int getExpected() { + if (value instanceof Integer) { + return Integer.bitCount((Integer) value); + } else if (value instanceof Long) { + return Long.bitCount((Long) value); + } + return -1; + } + } + + @Test + @SuppressWarnings("unchecked") + public void testBitCount() { + AArch64CodeGenTestCase[] tests = { + new AArch64BitCountCodeGenTestCase<>(0, JavaKind.Int.getByteCount() * Byte.SIZE), + new AArch64BitCountCodeGenTestCase<>(1522767384, JavaKind.Int.getByteCount() * Byte.SIZE), + new AArch64BitCountCodeGenTestCase<>(0L, JavaKind.Long.getByteCount() * Byte.SIZE), + new AArch64BitCountCodeGenTestCase<>(81985529216486895L, JavaKind.Long.getByteCount() * Byte.SIZE), + }; + + assertReturn("intStub", tests[0].create(), tests[0].getExpected(), ((AArch64BitCountCodeGenTestCase) tests[0]).getValue()); + assertReturn("intStub", tests[1].create(), tests[1].getExpected(), ((AArch64BitCountCodeGenTestCase) tests[1]).getValue()); + assertReturn("longStub", tests[2].create(), tests[2].getExpected(), ((AArch64BitCountCodeGenTestCase) tests[2]).getValue()); + assertReturn("longStub", tests[3].create(), tests[3].getExpected(), ((AArch64BitCountCodeGenTestCase) tests[3]).getValue()); + } + + @SuppressWarnings("unused") + public static int intStub(int x) { + return 0; + } + + @SuppressWarnings("unused") + public static int longStub(long x) { + return 0; + } +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64InstructionEncodingTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64InstructionEncodingTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64InstructionEncodingTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64InstructionEncodingTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Arm Limited. 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. + */ + + +package org.graalvm.compiler.asm.aarch64.test; + +import static org.junit.Assume.assumeTrue; + +import java.nio.ByteBuffer; + +import org.graalvm.compiler.asm.aarch64.AArch64Assembler; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.test.GraalTest; +import org.junit.Before; +import org.junit.Test; + +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.runtime.JVMCI; + +public class AArch64InstructionEncodingTest extends GraalTest { + @Before + public void checkAArch64() { + assumeTrue("skipping non AArch64 specific test", JVMCI.getRuntime().getHostJVMCIBackend().getTarget().arch instanceof AArch64); + } + + private abstract class AArch64InstructionEncodingTestCase { + private byte[] actual; + private byte[] expected; + TestProtectedAssembler assembler; + + AArch64InstructionEncodingTestCase(int expected) { + this.expected = ByteBuffer.allocate(Integer.BYTES).putInt(expected).array(); + TargetDescription target = JVMCI.getRuntime().getHostJVMCIBackend().getTarget(); + assembler = new TestProtectedAssembler(target); + } + + int getExpected() { + return ByteBuffer.wrap(expected).getInt(); + } + + int getActual() { + return ByteBuffer.wrap(actual).getInt(); + } + + void closeAssembler() { + this.actual = assembler.close(true); + } + } + + private class CntEncodingTestCase extends AArch64InstructionEncodingTestCase { + CntEncodingTestCase(int expected, int size, Register dst, Register src) { + super(expected); + assembler.cnt(size, dst, src); + closeAssembler(); + } + } + + private class AddvEncodingTestCase extends AArch64InstructionEncodingTestCase { + AddvEncodingTestCase(int expected, int size, AArch64Assembler.SIMDElementSize laneWidth, Register dst, Register src) { + super(expected); + assembler.addv(size, laneWidth, dst, src); + closeAssembler(); + } + } + + private class UmovEncodingTestCase extends AArch64InstructionEncodingTestCase { + UmovEncodingTestCase(int expected, int size, Register dst, int srcIdx, Register src) { + super(expected); + assembler.umov(size, dst, srcIdx, src); + closeAssembler(); + } + } + + private static final int invalidInstructionCode = 0x00000000; + + private void assertWrapper(AArch64InstructionEncodingTestCase testCase) { + assertDeepEquals(testCase.getActual(), testCase.getExpected()); + } + + @Test + public void testCnt() { + assertWrapper(new CntEncodingTestCase(0x0058200e, 64, AArch64.v0, AArch64.v0)); + assertWrapper(new CntEncodingTestCase(0x3f58204e, 128, AArch64.v31, AArch64.v1)); + } + + @Test(expected = AssertionError.class) + @SuppressWarnings("unused") + public void testCntWithInvalidDataSize() { + new CntEncodingTestCase(invalidInstructionCode, 32, AArch64.v5, AArch64.v5); + } + + @Test + public void testAddv() { + assertWrapper(new AddvEncodingTestCase(0x20b8310e, 64, AArch64Assembler.SIMDElementSize.Byte, AArch64.v0, AArch64.v1)); + assertWrapper(new AddvEncodingTestCase(0x42b8314e, 128, AArch64Assembler.SIMDElementSize.Byte, AArch64.v2, AArch64.v2)); + assertWrapper(new AddvEncodingTestCase(0xd2ba710e, 64, AArch64Assembler.SIMDElementSize.HalfWord, AArch64.v18, AArch64.v22)); + assertWrapper(new AddvEncodingTestCase(0x77ba714e, 128, AArch64Assembler.SIMDElementSize.HalfWord, AArch64.v23, AArch64.v19)); + assertWrapper(new AddvEncodingTestCase(0x18bbb14e, 128, AArch64Assembler.SIMDElementSize.Word, AArch64.v24, AArch64.v24)); + } + + @Test(expected = AssertionError.class) + @SuppressWarnings("unused") + public void testAddvWithInvalidSizeLaneCombo() { + new AddvEncodingTestCase(invalidInstructionCode, 64, AArch64Assembler.SIMDElementSize.Word, AArch64.v0, AArch64.v1); + } + + @Test(expected = AssertionError.class) + @SuppressWarnings("unused") + public void testAddvWithInvalidDataSize() { + new AddvEncodingTestCase(invalidInstructionCode, 32, AArch64Assembler.SIMDElementSize.Word, AArch64.v0, AArch64.v1); + } + + @Test(expected = AssertionError.class) + @SuppressWarnings("unused") + public void testAddvWithInvalidLane() { + new AddvEncodingTestCase(invalidInstructionCode, 128, AArch64Assembler.SIMDElementSize.DoubleWord, AArch64.v0, AArch64.v1); + } + + @Test + public void testUmov() { + assertWrapper(new UmovEncodingTestCase(0x1f3c084e, 64, AArch64.r31, 0, AArch64.v0)); + assertWrapper(new UmovEncodingTestCase(0xe13f184e, 64, AArch64.r1, 1, AArch64.v31)); + + assertWrapper(new UmovEncodingTestCase(0x5d3c040e, 32, AArch64.r29, 0, AArch64.v2)); + assertWrapper(new UmovEncodingTestCase(0x833f1c0e, 32, AArch64.r3, 3, AArch64.v28)); + + assertWrapper(new UmovEncodingTestCase(0x4b3d020e, 16, AArch64.r11, 0, AArch64.v10)); + assertWrapper(new UmovEncodingTestCase(0x893d1e0e, 16, AArch64.r9, 7, AArch64.v12)); + + assertWrapper(new UmovEncodingTestCase(0x0d3d010e, 8, AArch64.r13, 0, AArch64.v8)); + assertWrapper(new UmovEncodingTestCase(0xc73d1f0e, 8, AArch64.r7, 15, AArch64.v14)); + } + + @Test(expected = AssertionError.class) + @SuppressWarnings("unused") + public void testUmovInvalidSrcIdx() { + new UmovEncodingTestCase(invalidInstructionCode, 64, AArch64.r0, 2, AArch64.v0); + } + + @Test(expected = GraalError.class) + @SuppressWarnings("unused") + public void testUmovInvalidDataSize() { + new UmovEncodingTestCase(invalidInstructionCode, 31, AArch64.r0, 3, AArch64.v0); + } +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -549,4 +549,19 @@ public void ensureUniquePC() { throw new UnsupportedOperationException(); } + + @Override + public void cnt(int size, Register dst, Register src) { + super.cnt(size, dst, src); + } + + @Override + public void addv(int size, SIMDElementSize laneWidth, Register dst, Register src) { + super.addv(size, laneWidth, dst, src); + } + + @Override + public void umov(int size, Register dst, int srcIdx, Register src) { + super.umov(size, dst, srcIdx, src); + } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java 2019-04-24 19:25:41.000000000 +0000 @@ -75,7 +75,6 @@ import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize; -import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.debug.GraalError; @@ -1882,7 +1881,7 @@ // is the same however, seems to be rather unlikely case. // Note: use jccb() if label to be bound is very close to get // an 8-bit displacement - l.addPatchAt(position()); + l.addPatchAt(position(), this); emitByte(0x0F); emitByte(0x80 | cc.getValue()); emitInt(0); @@ -1900,7 +1899,7 @@ emitByte(0x70 | cc.getValue()); emitByte((int) ((disp - shortSize) & 0xFF)); } else { - l.addPatchAt(position()); + l.addPatchAt(position(), this); emitByte(0x70 | cc.getValue()); emitByte(0); } @@ -1929,7 +1928,7 @@ // the forward jump will not run beyond 256 bytes, use jmpb to // force an 8-bit displacement. - l.addPatchAt(position()); + l.addPatchAt(position(), this); emitByte(0xE9); emitInt(0); } @@ -1950,14 +1949,13 @@ public final void jmpb(Label l) { if (l.isBound()) { int shortSize = 2; - int entry = l.position(); - assert isByte((entry - position()) + shortSize) : "Dispacement too large for a short jmp"; - long offs = entry - position(); + // Displacement is relative to byte just after jmpb instruction + int displacement = l.position() - position() - shortSize; + GraalError.guarantee(isByte(displacement), "Displacement too large to be encoded as a byte: %d", displacement); emitByte(0xEB); - emitByte((int) ((offs - shortSize) & 0xFF)); + emitByte(displacement & 0xFF); } else { - - l.addPatchAt(position()); + l.addPatchAt(position(), this); emitByte(0xEB); emitByte(0); } @@ -3397,9 +3395,7 @@ * Since a wrongly patched short branch can potentially lead to working but really bad * behaving code we should always fail with an exception instead of having an assert. */ - if (!NumUtil.isByte(imm8)) { - throw new InternalError("branch displacement out of range: " + imm8); - } + GraalError.guarantee(isByte(imm8), "Displacement too large to be encoded as a byte: %d", imm8); emitByte(imm8, branch + 1); } else { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java 2019-04-24 19:25:41.000000000 +0000 @@ -1851,7 +1851,7 @@ } protected int patchUnbound(Label label) { - label.addPatchAt(position()); + label.addPatchAt(position(), this); return 0; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -252,7 +252,7 @@ if (!state.canProduceBytecodeFrame()) { // This typically means a snippet or intrinsic frame state made it to the backend - StackTraceElement ste = state.getCode().asStackTraceElement(state.bci); + String ste = state.getCode() != null ? state.getCode().asStackTraceElement(state.bci).toString() : state.toString(); throw new GraalError("Frame state for %s cannot be converted to a BytecodeFrame since the frame state's code is " + "not the same as the frame state method's code", ste); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR; import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ; import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.POPCNT; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.LIRKind; @@ -432,27 +433,30 @@ @Override public Value emitBitCount(Value operand) { - throw GraalError.unimplemented("AArch64 ISA does not offer way to implement this more efficiently than a simple Java algorithm."); + assert ((AArch64Kind) operand.getPlatformKind()).isInteger(); + Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(getLIRGen(), POPCNT, result, asAllocatable(operand))); + return result; } @Override public Value emitBitScanReverse(Value value) { Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); - getLIRGen().append(new AArch64BitManipulationOp(BSR, result, asAllocatable(value))); + getLIRGen().append(new AArch64BitManipulationOp(getLIRGen(), BSR, result, asAllocatable(value))); return result; } @Override public Value emitCountLeadingZeros(Value value) { Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); - getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, asAllocatable(value))); + getLIRGen().append(new AArch64BitManipulationOp(getLIRGen(), CLZ, result, asAllocatable(value))); return result; } @Override public Value emitCountTrailingZeros(Value value) { Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); - getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, asAllocatable(value))); + getLIRGen().append(new AArch64BitManipulationOp(getLIRGen(), CTZ, result, asAllocatable(value))); return result; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.aarch64; +import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; @@ -32,6 +33,7 @@ import jdk.internal.vm.compiler.collections.Equivalence; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.core.match.ComplexMatchResult; import org.graalvm.compiler.core.match.MatchRule; @@ -44,12 +46,14 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.AndNode; import org.graalvm.compiler.nodes.calc.BinaryNode; +import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; import org.graalvm.compiler.nodes.calc.LeftShiftNode; import org.graalvm.compiler.nodes.calc.NotNode; import org.graalvm.compiler.nodes.calc.OrNode; @@ -59,8 +63,6 @@ import org.graalvm.compiler.nodes.calc.XorNode; import org.graalvm.compiler.nodes.memory.Access; -import jdk.vm.ci.aarch64.AArch64Kind; - public class AArch64NodeMatchRules extends NodeMatchRules { private static final EconomicMap, AArch64ArithmeticOp> nodeOpMap; @@ -99,7 +101,8 @@ return getLIRGeneratorTool().moveSp(value); } - private ComplexMatchResult emitBinaryShift(AArch64ArithmeticOp op, ValueNode value, BinaryNode shift, boolean isShiftNot) { + private ComplexMatchResult emitBinaryShift(AArch64ArithmeticOp op, ValueNode value, BinaryNode shift, + boolean isShiftNot) { AArch64MacroAssembler.ShiftType shiftType = shiftTypeMap.get(shift.getClass()); assert shiftType != null; assert value.getStackKind().isNumericInteger(); @@ -118,6 +121,18 @@ }; } + private ComplexMatchResult emitBitTestAndBranch(FixedNode trueSuccessor, FixedNode falseSuccessor, + ValueNode value, double trueProbability, int nbits) { + return builder -> { + LabelRef trueDestination = getLIRBlock(trueSuccessor); + LabelRef falseDestination = getLIRBlock(falseSuccessor); + AllocatableValue src = moveSp(gen.asAllocatable(operand(value))); + gen.append(new AArch64ControlFlow.BitTestAndBranchOp(trueDestination, falseDestination, src, + trueProbability, nbits)); + return null; + }; + } + @MatchRule("(Add=binary a (LeftShift=shift b Constant))") @MatchRule("(Add=binary a (RightShift=shift b Constant))") @MatchRule("(Add=binary a (UnsignedRightShift=shift b Constant))") @@ -189,19 +204,26 @@ if (value.getStackKind().isNumericInteger()) { long constant = a.asJavaConstant().asLong(); if (Long.bitCount(constant) == 1) { - int bitToTest = Long.numberOfTrailingZeros(constant); - return builder -> { - LabelRef trueDestination = getLIRBlock(root.trueSuccessor()); - LabelRef falseDestination = getLIRBlock(root.falseSuccessor()); - AllocatableValue src = moveSp(gen.asAllocatable(operand(value))); - double trueDestinationProbability = root.getTrueSuccessorProbability(); - gen.append(new AArch64ControlFlow.BitTestAndBranchOp(trueDestination, falseDestination, src, trueDestinationProbability, bitToTest)); - return null; - }; + return emitBitTestAndBranch(root.trueSuccessor(), root.falseSuccessor(), value, + root.getTrueSuccessorProbability(), Long.numberOfTrailingZeros(constant)); } } return null; } + + /** + * if x < 0 <=> tbz x, sizeOfBits(x) - 1, label. + */ + @MatchRule("(If (IntegerLessThan=lessNode x Constant=y))") + public ComplexMatchResult checkNegativeAndBranch(IfNode root, IntegerLessThanNode lessNode, ValueNode x, ConstantNode y) { + JavaKind xKind = x.getStackKind(); + assert xKind.isNumericInteger(); + if (y.isJavaConstant() && (0 == y.asJavaConstant().asLong()) && lessNode.condition().equals(CanonicalCondition.LT)) { + return emitBitTestAndBranch(root.falseSuccessor(), root.trueSuccessor(), x, + 1.0 - root.getTrueSuccessorProbability(), xKind.getBitCount() - 1); + } + return null; + } @Override public AArch64LIRGenerator getLIRGeneratorTool() { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,10 +24,9 @@ package org.graalvm.compiler.core.aarch64.test; -import static org.junit.Assume.assumeTrue; - -import java.util.function.Predicate; - +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.Value; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.lir.LIR; @@ -48,9 +47,9 @@ import org.junit.Before; import org.junit.Test; -import jdk.vm.ci.aarch64.AArch64; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.meta.Value; +import java.util.function.Predicate; + +import static org.junit.Assume.assumeTrue; public class AArch64TestBitAndBranchTest extends LIRTest { private static final Predicate checkForBitTestAndBranchOp = op -> (op instanceof AArch64ControlFlow.BitTestAndBranchOp); @@ -62,7 +61,7 @@ } public static long testBit42Snippet(long a, long b, long c) { - if ((a & (1 << 42)) == 0) { + if ((a & (1L << 42)) == 0) { return b; } else { return c; @@ -71,12 +70,12 @@ @Test public void testBit42() { - test("testBit42Snippet", 1L << 42L, Long.MAX_VALUE, Long.MIN_VALUE); - test("testBit42Snippet", ~(1L << 42L), Long.MAX_VALUE, Long.MIN_VALUE); + test("testBit42Snippet", 1L << 42, Long.MAX_VALUE, Long.MIN_VALUE); + test("testBit42Snippet", ~(1L << 42), Long.MAX_VALUE, Long.MIN_VALUE); checkLIR("testBit42Snippet", checkForBitTestAndBranchOp, 1); } - private static final LargeOpSpec largeOpSingleNop = new LargeOpSpec((1 << 14 - 2), 2); + private static final LargeOpSpec largeOpSingleNop = new LargeOpSpec((1 << 14 - 2) - 10, 2); /** * Tests the graceful case, where the estimation for @@ -99,7 +98,7 @@ checkLIR("testBitTestAndBranchSingleSnippet", checkForBitTestAndBranchOp, 1); } - private static final LargeOpSpec largeOpFourNop = new LargeOpSpec((1 << 14 - 2), 8); + private static final LargeOpSpec largeOpFourNop = new LargeOpSpec((1 << 14 - 2) - 10, 8); /** * Tests the case, where the estimation for @@ -122,6 +121,73 @@ checkLIR("testBitTestAndBranchFourSnippet", checkForBitTestAndBranchOp, 1); } + private static final float trueTarget = Float.MAX_VALUE; + private static final float falseTarget = Float.MIN_VALUE; + + public static float testLessThanZeroSnippet(long a, long b) { + if (b + a - b < 0) { + return trueTarget - a; + } else { + return falseTarget + a; + } + } + + @Test + public void testLessThanZero() { + test("testLessThanZeroSnippet", 1L, 777L); + test("testLessThanZeroSnippet", 0L, 777L); + test("testLessThanZeroSnippet", -1L, 777L); + checkLIR("testLessThanZeroSnippet", checkForBitTestAndBranchOp, 1); + } + + public static float testLessThanEqualZeroSnippet(long a) { + if (a <= 0) { + return trueTarget - a; + } else { + return falseTarget + a; + } + } + + @Test + public void testLessThanEqualZero() { + test("testLessThanEqualZeroSnippet", 1L); + test("testLessThanEqualZeroSnippet", 0L); + test("testLessThanEqualZeroSnippet", -1L); + checkLIR("testLessThanEqualZeroSnippet", checkForBitTestAndBranchOp, 0); + } + + public static float testGreaterThanZeroSnippet(int a) { + if (a > 0) { + return trueTarget - a; + } else { + return falseTarget + a; + } + } + + @Test + public void testGreaterThanZero() { + test("testGreaterThanZeroSnippet", 1); + test("testGreaterThanZeroSnippet", 0); + test("testGreaterThanZeroSnippet", -1); + checkLIR("testGreaterThanZeroSnippet", checkForBitTestAndBranchOp, 0); + } + + public static float testGreaterThanEqualZeroSnippet(int a) { + if (a >= 0) { + return trueTarget - a; + } else { + return falseTarget + a; + } + } + + @Test + public void testGreaterThanEqualZero() { + test("testGreaterThanEqualZeroSnippet", 1); + test("testGreaterThanEqualZeroSnippet", 0); + test("testGreaterThanEqualZeroSnippet", -1); + checkLIR("testGreaterThanEqualZeroSnippet", checkForBitTestAndBranchOp, 1); + } + private static class LargeOpSpec extends LIRTestSpecification { private final int n; private final int nopCount; @@ -172,7 +238,9 @@ public class CheckPhase extends LIRPhase { @Override - protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) { + protected void run( + TargetDescription target, LIRGenerationResult lirGenRes, + PreAllocationOptimizationContext context) { lir = lirGenRes.getLIR(); } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java 2019-04-24 19:25:41.000000000 +0000 @@ -282,4 +282,6 @@ @Option(help = "Use Graal-generated stubs for complicated LIR operations instead of embedding all the emitted code.") public static final OptionKey UseGraalStubs = new OptionKey<>(true); + @Option(help = "Encode and decode snippets and substitutions before parsing to test libgraal code path. This option is ignored in the context of libgraal.") + public static final OptionKey UseEncodedGraphs = new OptionKey<>(false); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java 2019-04-24 19:25:41.000000000 +0000 @@ -61,4 +61,9 @@ * Gets the linkage for a foreign call. */ ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor); + + /** + * Return true if the foreign call has a binding. + */ + boolean isAvailable(ForeignCallDescriptor descriptor); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java 2019-04-24 19:25:41.000000000 +0000 @@ -643,7 +643,7 @@ IntegerStamp b = (IntegerStamp) stamp2; int bits = a.getBits(); - assert bits == b.getBits(); + assert bits == b.getBits() : String.format("stamp1.bits=%d, stamp2.bits=%d", bits, b.getBits()); if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound) { long value = CodeUtil.convert(a.lowerBound() + b.lowerBound(), a.getBits(), false); @@ -1298,6 +1298,15 @@ } } + private boolean testNoSignChangeAfterShifting(int bits, long value, int shiftAmount) { + long removedBits = -1L << (bits - shiftAmount - 1); + if (value < 0) { + return (value & removedBits) == removedBits; + } else { + return (value & removedBits) == 0; + } + } + @Override public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { IntegerStamp value = (IntegerStamp) stamp; @@ -1318,13 +1327,15 @@ return value; } // the mask of bits that will be lost or shifted into the sign bit - long removedBits = -1L << (bits - shiftAmount - 1); - if ((value.lowerBound() & removedBits) == 0 && (value.upperBound() & removedBits) == 0) { + if (testNoSignChangeAfterShifting(bits, value.lowerBound(), shiftAmount) && testNoSignChangeAfterShifting(bits, value.upperBound(), shiftAmount)) { /* * use a better stamp if neither lower nor upper bound can lose * bits */ - return new IntegerStamp(bits, value.lowerBound() << shiftAmount, value.upperBound() << shiftAmount, value.downMask() << shiftAmount, value.upMask() << shiftAmount); + IntegerStamp result = new IntegerStamp(bits, value.lowerBound() << shiftAmount, value.upperBound() << shiftAmount, + (value.downMask() << shiftAmount) & CodeUtil.mask(bits), + (value.upMask() << shiftAmount) & CodeUtil.mask(bits)); + return result; } } if ((shift.lowerBound() >>> shiftBits) == (shift.upperBound() >>> shiftBits)) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/AbstractTypeReader.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/AbstractTypeReader.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/AbstractTypeReader.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/AbstractTypeReader.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.core.common.util; + +public abstract class AbstractTypeReader implements TypeReader { + @Override + public long getSV() { + return decodeSign(read()); + } + + @Override + public long getUV() { + return read(); + } + + public static long decodeSign(long value) { + return (value >>> 1) ^ -(value & 1); + } + + private long read() { + int b0 = getU1(); + if (b0 < UnsafeArrayTypeWriter.NUM_LOW_CODES) { + return b0; + } else { + return readPacked(b0); + } + } + + private long readPacked(int b0) { + assert b0 >= UnsafeArrayTypeWriter.NUM_LOW_CODES; + long sum = b0; + long shift = UnsafeArrayTypeWriter.HIGH_WORD_SHIFT; + for (int i = 2;; i++) { + long b = getU1(); + sum += b << shift; + if (b < UnsafeArrayTypeWriter.NUM_LOW_CODES || i == UnsafeArrayTypeWriter.MAX_BYTES) { + return sum; + } + shift += UnsafeArrayTypeWriter.HIGH_WORD_SHIFT; + } + } +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeReader.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeReader.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeReader.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeReader.java 2019-04-24 19:25:41.000000000 +0000 @@ -60,21 +60,7 @@ * Reads a signed value that has been written using {@link TypeWriter#putSV variable byte size * encoding}. */ - default long getSV() { - long result = 0; - int shift = 0; - long b; - do { - b = getU1(); - result |= (b & 0x7f) << shift; - shift += 7; - } while ((b & 0x80) != 0); - - if ((b & 0x40) != 0 && shift < 64) { - result |= -1L << shift; - } - return result; - } + long getSV(); /** * Reads a signed variable byte size encoded value that is known to fit into the range of int. @@ -87,18 +73,7 @@ * Reads an unsigned value that has been written using {@link TypeWriter#putSV variable byte * size encoding}. */ - default long getUV() { - long result = 0; - int shift = 0; - long b; - do { - b = getU1(); - result |= (b & 0x7f) << shift; - shift += 7; - } while ((b & 0x80) != 0); - - return result; - } + long getUV(); /** * Reads an unsigned variable byte size encoded value that is known to fit into the range of diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeWriter.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeWriter.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -29,7 +29,6 @@ * bytes. */ public interface TypeWriter { - /** * Returns the number of bytes that have been written, i.e., the byte index of the next byte to * be written. @@ -51,40 +50,18 @@ /** Writes a signed 4 byte value. */ void putS4(long value); + /** Patches a previously written signed 4 byte value at a given offset. */ + void patchS4(long value, long offset); + /** Writes an unsigned 4 byte value. */ void putU4(long value); /** Writes a signed 8 byte value. */ void putS8(long value); - /** - * Writes a signed value in a variable byte size encoding. - */ - default void putSV(long value) { - long cur = value; - while (true) { - if (cur >= -64 && cur < 64) { - putU1(cur & 0x7f); - return; - } - putU1(0x80 | (cur & 0x7f)); - cur = cur >> 7; - } - } + /** Writes a signed value in a variable byte size encoding. */ + void putSV(long value); - /** - * Writes an unsigned value in a variable byte size encoding. - */ - default void putUV(long value) { - long cur = value; - while (true) { - assert cur >= 0; - if (cur < 128) { - putU1(cur & 0x7f); - return; - } - putU1(0x80 | (cur & 0x7f)); - cur = cur >> 7; - } - } + /** Writes an unsigned value in a variable byte size encoding. */ + void putUV(long value); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeReader.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeReader.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeReader.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeReader.java 2019-04-24 19:25:41.000000000 +0000 @@ -40,7 +40,7 @@ * architectures that support unaligned memory accesses; the value {@code false} is the safe * fallback that works on every hardware. */ -public abstract class UnsafeArrayTypeReader implements TypeReader { +public abstract class UnsafeArrayTypeReader extends AbstractTypeReader { private static final Unsafe UNSAFE = getUnsafe(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import static org.graalvm.compiler.core.common.util.TypeConversion.asU4; import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; +import org.graalvm.compiler.core.common.calc.UnsignedMath; + import sun.misc.Unsafe; /** @@ -45,11 +47,16 @@ * fallback that works on every hardware. */ public abstract class UnsafeArrayTypeWriter implements TypeWriter { - private static final Unsafe UNSAFE = getUnsafe(); private static final int MIN_CHUNK_LENGTH = 200; private static final int MAX_CHUNK_LENGTH = 16000; + // Constants for UNSIGNED5 coding of Pack200 + public static final long HIGH_WORD_SHIFT = 6; + public static final long NUM_HIGH_CODES = 1 << HIGH_WORD_SHIFT; // number of high codes (64) + public static final long NUM_LOW_CODES = (1 << Byte.SIZE) - NUM_HIGH_CODES; + public static final long MAX_BYTES = 11; + static class Chunk { protected final byte[] data; protected int size; @@ -118,6 +125,30 @@ putS4(asU4(value)); } + @Override + public void putS2(long value) { + long offset = writeOffset(Short.BYTES); + putS2(value, writeChunk, offset); + } + + @Override + public void putS4(long value) { + long offset = writeOffset(Integer.BYTES); + putS4(value, writeChunk, offset); + } + + @Override + public void putS8(long value) { + long offset = writeOffset(Long.BYTES); + putS8(value, writeChunk, offset); + } + + protected abstract void putS2(long value, Chunk chunk, long offset); + + protected abstract void putS4(long value, Chunk chunk, long offset); + + protected abstract void putS8(long value, Chunk chunk, long offset); + protected long writeOffset(int writeBytes) { if (writeChunk.size + writeBytes >= writeChunk.data.length) { Chunk newChunk = new Chunk(Math.min(writeChunk.data.length * 2, MAX_CHUNK_LENGTH)); @@ -134,27 +165,76 @@ return result; } + + @Override + public void patchS4(long value, long offset) { + long chunkStartOffset = 0; + Chunk chunk = firstChunk; + while (chunkStartOffset + chunk.size <= offset) { + chunkStartOffset += chunk.size; + chunk = chunk.next; + } + + long targetOffset = offset - chunkStartOffset; + assert targetOffset + Integer.BYTES <= chunk.size : "out of bounds"; + putS4(value, chunk, Unsafe.ARRAY_BYTE_BASE_OFFSET + targetOffset); + } + + @Override + public void putSV(long value) { + // this is a modified version of the SIGNED5 encoding from Pack200 + write(encodeSign(value)); + } + + @Override + public void putUV(long value) { + // this is a modified version of the UNSIGNED5 encoding from Pack200 + write(value); + } + + private static long encodeSign(long value) { + return (value << 1) ^ (value >> 63); + } + + private void write(long value) { + if (UnsignedMath.belowThan(value, NUM_LOW_CODES)) { + putU1(value); + } else { + writePacked(value); + } + } + + private void writePacked(long value) { + long sum = value; + for (int i = 1; UnsignedMath.aboveOrEqual(sum, NUM_LOW_CODES) && i < MAX_BYTES; i++) { + sum -= NUM_LOW_CODES; + long u1 = NUM_LOW_CODES + (sum & (NUM_HIGH_CODES - 1)); // this is a "high code" + sum >>>= HIGH_WORD_SHIFT; // extracted 6 bits + putU1(u1); + } + + // remainder is either a "low code" or the last byte + assert sum == (sum & 0xFF) : "not a byte"; + putU1(sum & 0xFF); + } } final class UnalignedUnsafeArrayTypeWriter extends UnsafeArrayTypeWriter { private static final Unsafe UNSAFE = getUnsafe(); @Override - public void putS2(long value) { - long offset = writeOffset(Short.BYTES); - UNSAFE.putShort(writeChunk.data, offset, asS2(value)); + protected void putS2(long value, Chunk chunk, long offset) { + UNSAFE.putShort(chunk.data, offset, asS2(value)); } @Override - public void putS4(long value) { - long offset = writeOffset(Integer.BYTES); - UNSAFE.putInt(writeChunk.data, offset, asS4(value)); + protected void putS4(long value, Chunk chunk, long offset) { + UNSAFE.putInt(chunk.data, offset, asS4(value)); } @Override - public void putS8(long value) { - long offset = writeOffset(Long.BYTES); - UNSAFE.putLong(writeChunk.data, offset, value); + protected void putS8(long value, Chunk chunk, long offset) { + UNSAFE.putLong(chunk.data, offset, value); } } @@ -162,31 +242,28 @@ private static final Unsafe UNSAFE = getUnsafe(); @Override - public void putS2(long value) { - long offset = writeOffset(Short.BYTES); - UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0)); - UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8)); + protected void putS2(long value, Chunk chunk, long offset) { + UNSAFE.putByte(chunk.data, offset + 0, (byte) (value >> 0)); + UNSAFE.putByte(chunk.data, offset + 1, (byte) (value >> 8)); } @Override - public void putS4(long value) { - long offset = writeOffset(Integer.BYTES); - UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0)); - UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8)); - UNSAFE.putByte(writeChunk.data, offset + 2, (byte) (value >> 16)); - UNSAFE.putByte(writeChunk.data, offset + 3, (byte) (value >> 24)); + protected void putS4(long value, Chunk chunk, long offset) { + UNSAFE.putByte(chunk.data, offset + 0, (byte) (value >> 0)); + UNSAFE.putByte(chunk.data, offset + 1, (byte) (value >> 8)); + UNSAFE.putByte(chunk.data, offset + 2, (byte) (value >> 16)); + UNSAFE.putByte(chunk.data, offset + 3, (byte) (value >> 24)); } @Override - public void putS8(long value) { - long offset = writeOffset(Long.BYTES); - UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0)); - UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8)); - UNSAFE.putByte(writeChunk.data, offset + 2, (byte) (value >> 16)); - UNSAFE.putByte(writeChunk.data, offset + 3, (byte) (value >> 24)); - UNSAFE.putByte(writeChunk.data, offset + 4, (byte) (value >> 32)); - UNSAFE.putByte(writeChunk.data, offset + 5, (byte) (value >> 40)); - UNSAFE.putByte(writeChunk.data, offset + 6, (byte) (value >> 48)); - UNSAFE.putByte(writeChunk.data, offset + 7, (byte) (value >> 56)); + protected void putS8(long value, Chunk chunk, long offset) { + UNSAFE.putByte(chunk.data, offset + 0, (byte) (value >> 0)); + UNSAFE.putByte(chunk.data, offset + 1, (byte) (value >> 8)); + UNSAFE.putByte(chunk.data, offset + 2, (byte) (value >> 16)); + UNSAFE.putByte(chunk.data, offset + 3, (byte) (value >> 24)); + UNSAFE.putByte(chunk.data, offset + 4, (byte) (value >> 32)); + UNSAFE.putByte(chunk.data, offset + 5, (byte) (value >> 40)); + UNSAFE.putByte(chunk.data, offset + 6, (byte) (value >> 48)); + UNSAFE.putByte(chunk.data, offset + 7, (byte) (value >> 56)); } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BasePhaseBinaryGraphTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BasePhaseBinaryGraphTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BasePhaseBinaryGraphTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BasePhaseBinaryGraphTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -24,11 +24,12 @@ package org.graalvm.compiler.core.test; +import static org.junit.Assert.assertEquals; + import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.printer.BinaryGraphPrinter; -import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; @@ -43,7 +44,7 @@ @Before public void createPrinter() throws Exception { - printer = new BinaryGraphPrinter(DebugContext.DISABLED, null); + printer = new BinaryGraphPrinter(DebugContext.disabled(null), null); } @Test diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -51,7 +51,7 @@ StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES, debug); boolean resetSucceeded = false; try (Scope scope = debug.scope("some scope")) { - graph.resetDebug(DebugContext.DISABLED); + graph.resetDebug(DebugContext.disabled(getInitialOptions())); resetSucceeded = true; } catch (AssertionError expected) { } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -141,13 +141,13 @@ test01(false); } - private static void checkSignedSize(TypeWriter writer, long value, int expectedSize) { + private static void checkSignedSize(TypeWriter writer, long value, long expectedSize) { long sizeBefore = writer.getBytesWritten(); writer.putSV(value); Assert.assertEquals(expectedSize, writer.getBytesWritten() - sizeBefore); } - private static void checkUnsignedSize(TypeWriter writer, long value, int expectedSize) { + private static void checkUnsignedSize(TypeWriter writer, long value, long expectedSize) { long sizeBefore = writer.getBytesWritten(); writer.putUV(value); Assert.assertEquals(expectedSize, writer.getBytesWritten() - sizeBefore); @@ -155,23 +155,24 @@ private static void checkSizes(TypeWriter writer) { checkSignedSize(writer, 0, 1); - checkSignedSize(writer, 63, 1); - checkSignedSize(writer, -64, 1); - checkSignedSize(writer, 64, 2); - checkSignedSize(writer, -65, 2); - checkSignedSize(writer, 8191, 2); - checkSignedSize(writer, -8192, 2); + checkSignedSize(writer, 95, 1); + checkSignedSize(writer, -96, 1); + checkSignedSize(writer, 96, 2); + checkSignedSize(writer, -97, 2); + checkSignedSize(writer, 6239, 2); + checkSignedSize(writer, -6240, 2); checkSignedSize(writer, 8192, 3); checkSignedSize(writer, -8193, 3); - checkSignedSize(writer, Long.MAX_VALUE, 10); - checkSignedSize(writer, Long.MIN_VALUE, 10); + checkSignedSize(writer, Long.MAX_VALUE, UnsafeArrayTypeWriter.MAX_BYTES); + checkSignedSize(writer, Long.MIN_VALUE, UnsafeArrayTypeWriter.MAX_BYTES); checkUnsignedSize(writer, 0, 1); - checkUnsignedSize(writer, 127, 1); - checkUnsignedSize(writer, 128, 2); - checkUnsignedSize(writer, 16383, 2); - checkUnsignedSize(writer, 16384, 3); - checkUnsignedSize(writer, Long.MAX_VALUE, 9); + checkUnsignedSize(writer, 191, 1); + checkUnsignedSize(writer, 192, 2); + checkUnsignedSize(writer, 12479, 2); + checkUnsignedSize(writer, 12480, 3); + checkUnsignedSize(writer, Long.MAX_VALUE, UnsafeArrayTypeWriter.MAX_BYTES); + checkUnsignedSize(writer, Long.MIN_VALUE, UnsafeArrayTypeWriter.MAX_BYTES); } @Test diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java 2019-04-24 19:25:41.000000000 +0000 @@ -311,9 +311,19 @@ } /** - * Shared object used to represent a disabled debug context. + * Singleton used to represent a disabled debug context. */ - public static final DebugContext DISABLED = new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, new Immutable(), NO_CONFIG_CUSTOMIZERS); + private static final DebugContext DISABLED = new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, new Immutable(), NO_CONFIG_CUSTOMIZERS); + + /** + * Create a DebugContext with debugging disabled. + */ + public static DebugContext disabled(OptionValues options) { + if (options == null || options.getMap().isEmpty()) { + return DISABLED; + } + return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), NO_CONFIG_CUSTOMIZERS); + } /** * Gets the debug context for the current thread. This should only be used when there is no diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java 2019-04-24 19:25:41.000000000 +0000 @@ -192,6 +192,11 @@ * {@code true}. */ boolean injectedStampIsNonNull() default false; + + /** + * If {@code true} then this is lowered into a node that has side effects. + */ + boolean hasSideEffect() default false; } /** diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java 2019-04-24 19:25:41.000000000 +0000 @@ -201,16 +201,24 @@ size = other.size; } - public boolean equals(NodeList other) { - if (size != other.size) { - return false; + @Override + public boolean equals(Object other) { + if (other == this) { + return true; } - for (int i = 0; i < size; i++) { - if (nodes[i] != other.nodes[i]) { + if (other instanceof List) { + List otherList = (List) other; + if (size != otherList.size()) { return false; } + for (int i = 0; i < size; i++) { + if (nodes[i] != otherList.get(i)) { + return false; + } + } + return true; } - return true; + return false; } @SuppressWarnings("unchecked") diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java 2019-04-24 19:25:41.000000000 +0000 @@ -178,6 +178,10 @@ StackTraceElement[] stackTraceNow = t.getStackTrace(); TTY.printf("Printing stack trace for current compilation of %s lasting more than %d seconds:%n%s", fmt(request1.getMethod()), EPOCH, fmt(stackTraceNow)); + + // Fortify: Null Dereference false positive + assert stacksAtTimeout != null; + if (Arrays.equals(stacksAtTimeout.get(t), stackTraceNow)) { TTY.printf("\t** Identical stack trace %d seconds ago, implying a hung compilation **%n", EPOCH); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java 2019-04-24 19:25:41.000000000 +0000 @@ -40,7 +40,6 @@ import org.graalvm.compiler.core.CompilationPrinter; import org.graalvm.compiler.core.CompilationWrapper; import org.graalvm.compiler.core.common.CompilationIdentifier; -import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; @@ -93,7 +92,6 @@ private final boolean useProfilingInfo; private final boolean shouldRetainLocalVariables; - private final OptionValues options; final class HotSpotCompilationWrapper extends CompilationWrapper { private final EventProvider.CompilationEvent compilationEvent; @@ -150,9 +148,8 @@ if (bailout.isPermanent()) { // Respect current action if it has been explicitly set. if (!CompilationBailoutAsFailure.hasBeenSet(values)) { - // Get more info for permanent bailouts during bootstrap - // or when assertions are enabled. - if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) { + // Get more info for permanent bailouts during bootstrap. + if (compiler.getGraalRuntime().isBootstrapping()) { return Diagnose; } @@ -165,9 +162,8 @@ // Respect current action if it has been explicitly set. if (!CompilationFailureAction.hasBeenSet(values)) { - // Automatically exit on failure during bootstrap - // or when assertions are enabled. - if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) { + // Automatically exit on failure during bootstrap. + if (compiler.getGraalRuntime().isBootstrapping()) { return ExitVM; } } @@ -180,14 +176,14 @@ HotSpotResolvedJavaMethod method = getMethod(); int entryBCI = getEntryBCI(); final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; - CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); + CompilationStatistics stats = CompilationStatistics.create(debug.getOptions(), method, isOSR); - final CompilationPrinter printer = CompilationPrinter.begin(options, compilationId, method, entryBCI); + final CompilationPrinter printer = CompilationPrinter.begin(debug.getOptions(), compilationId, method, entryBCI); try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { // Begin the compilation event. compilationEvent.begin(); - result = compiler.compile(method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, compilationId, options, debug); + result = compiler.compile(method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, compilationId, debug); } catch (Throwable e) { throw debug.handle(e); } finally { @@ -211,20 +207,21 @@ } - public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault, - OptionValues options) { - this(jvmciRuntime, compiler, request, useProfilingInfo, false, installAsDefault, options); + public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault) { + this(jvmciRuntime, compiler, request, useProfilingInfo, false, installAsDefault); } public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean shouldRetainLocalVariables, - boolean installAsDefault, OptionValues options) { + boolean installAsDefault) { this.jvmciRuntime = jvmciRuntime; this.compiler = compiler; this.compilationId = new HotSpotCompilationIdentifier(request); this.useProfilingInfo = useProfilingInfo; this.shouldRetainLocalVariables = shouldRetainLocalVariables; this.installAsDefault = installAsDefault; + } + public OptionValues filterOptions(OptionValues options) { /* * Disable inlining if HotSpot has it disabled unless it's been explicitly set in Graal. */ @@ -243,7 +240,7 @@ newOptions = new OptionValues(options, m); } } - this.options = newOptions; + return newOptions; } public HotSpotResolvedJavaMethod getMethod() { @@ -309,7 +306,8 @@ */ public static final TimerKey CodeInstallationTime = DebugContext.timer("CodeInstallation"); - public HotSpotCompilationRequestResult runCompilation() { + public HotSpotCompilationRequestResult runCompilation(OptionValues initialOptions) { + OptionValues options = filterOptions(initialOptions); SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection(); try (DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(snippetReflection))) { return runCompilation(debug); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java 2019-04-24 19:25:41.000000000 +0000 @@ -219,6 +219,8 @@ factory = candidates.get(0); } } + assert factory != null; + ShowConfigurationLevel level = Options.ShowConfiguration.getValue(options); if (level != ShowConfigurationLevel.none) { switch (level) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java 2019-04-24 19:25:41.000000000 +0000 @@ -102,6 +102,7 @@ private final boolean useSHA256Intrinsics = getFlag("UseSHA256Intrinsics", Boolean.class); private final boolean useSHA512Intrinsics = getFlag("UseSHA512Intrinsics", Boolean.class); private final boolean useGHASHIntrinsics = getFlag("UseGHASHIntrinsics", Boolean.class, false); + private final boolean useBase64Intrinsics = getFlag("UseBASE64Intrinsics", Boolean.class, false); private final boolean useMontgomeryMultiplyIntrinsic = getFlag("UseMontgomeryMultiplyIntrinsic", Boolean.class, false); private final boolean useMontgomerySquareIntrinsic = getFlag("UseMontgomerySquareIntrinsic", Boolean.class, false); private final boolean useMulAddIntrinsic = getFlag("UseMulAddIntrinsic", Boolean.class, false); @@ -132,6 +133,10 @@ return useGHASHIntrinsics && ghashProcessBlocks != 0; } + public boolean useBase64Intrinsics() { + return useBase64Intrinsics && base64EncodeBlock != 0; + } + public boolean useMontgomeryMultiplyIntrinsic() { return useMontgomeryMultiplyIntrinsic && montgomeryMultiply != 0; } @@ -647,6 +652,7 @@ public final long counterModeAESCrypt = getFieldValue("StubRoutines::_counterMode_AESCrypt", Long.class, "address", 0L); public final long ghashProcessBlocks = getFieldValue("StubRoutines::_ghash_processBlocks", Long.class, "address", 0L); + public final long base64EncodeBlock = getFieldValue("StubRoutines::_base64_encodeBlock", Long.class, "address", 0L); public final long crc32cTableTddr = getFieldValue("StubRoutines::_crc32c_table_addr", Long.class, "address", 0L); public final long updateBytesCRC32C = getFieldValue("StubRoutines::_updateBytesCRC32C", Long.class, "address", 0L); public final long updateBytesAdler32 = getFieldValue("StubRoutines::_updateBytesAdler32", Long.class, "address", 0L); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java 2019-04-24 19:25:41.000000000 +0000 @@ -306,6 +306,11 @@ public static final ForeignCallDescriptor GHASH_PROCESS_BLOCKS = new ForeignCallDescriptor("ghashProcessBlocks", void.class, Word.class, Word.class, Word.class, int.class); /** + * Descriptor for {@code StubRoutines::_base64_encodeBlock}. + */ + public static final ForeignCallDescriptor BASE64_ENCODE_BLOCK = new ForeignCallDescriptor("base64EncodeBlock", void.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class); + + /** * Descriptor for {@code StubRoutines::_counterMode_AESCrypt}. */ public static final ForeignCallDescriptor COUNTERMODE_IMPL_CRYPT = new ForeignCallDescriptor("counterModeAESCrypt", int.class, Word.class, Word.class, Word.class, Word.class, int.class, diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -280,14 +280,14 @@ } } } - assert !siteListIterator.hasNext() || site.pcOffset >= source.getStartOffset(); + assert !siteListIterator.hasNext() || (site != null && site.pcOffset >= source.getStartOffset()); if (site != null && source.getStartOffset() <= site.pcOffset && site.pcOffset <= source.getEndOffset()) { // Conflicting source mapping, skip it. continue; } else { // Since the sites are sorted there can not be any more sites in this interval. } - assert !siteListIterator.hasNext() || site.pcOffset > source.getEndOffset(); + assert !siteListIterator.hasNext() || (site != null && site.pcOffset > source.getEndOffset()); // Good source mapping. Create an infopoint and add it to the list. NodeSourcePosition sourcePosition = source.getSourcePosition(); assert sourcePosition.verify(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -283,7 +283,7 @@ @Override public boolean mayContainFP() { - return transition != Transition.LEAF_NOFP; + return transition != Transition.LEAF_NO_VZERO; } @Override diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java 2019-04-24 19:25:41.000000000 +0000 @@ -53,11 +53,14 @@ */ enum Transition { /** - * A call to a leaf function that is guaranteed to not use floating point registers and will - * never have its caller stack inspected by the VM. That is, {@code JavaFrameAnchor} - * management around the call can be omitted. + * A call to a leaf function that is guaranteed to not use floating point registers. + * Consequently, floating point registers cleanup will be waived. On AMD64, this means the + * compiler will no longer emit vzeroupper instruction around the foreign call, which it + * normally does for unknown foreign calls to avoid potential SSE-AVX transition penalty. + * Besides, this foreign call will never have its caller stack inspected by the VM. That is, + * {@code JavaFrameAnchor} management around the call can be omitted. */ - LEAF_NOFP, + LEAF_NO_VZERO, /** * A call to a leaf function that might use floating point registers but will never have its diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,7 +25,6 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; -import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -59,6 +58,7 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; +import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequestResult; @@ -109,7 +109,7 @@ } @SuppressWarnings("try") - CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues options) { + CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues initialOptions) { if (graalRuntime.isShutdown()) { return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false); } @@ -117,7 +117,7 @@ ResolvedJavaMethod method = request.getMethod(); if (graalRuntime.isBootstrapping()) { - if (DebugOptions.BootstrapInitializeOnly.getValue(options)) { + if (DebugOptions.BootstrapInitializeOnly.getValue(initialOptions)) { return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", DebugOptions.BootstrapInitializeOnly.getName()), true); } if (bootstrapWatchDog != null) { @@ -128,13 +128,14 @@ } } HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request; + CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, shouldRetainLocalVariables(hsRequest.getJvmciEnv()), installAsDefault); + OptionValues options = task.filterOptions(initialOptions); try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options); BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request); CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) { if (compilationCounters != null) { compilationCounters.countCompilation(method); } - CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, shouldRetainLocalVariables(hsRequest.getJvmciEnv()), installAsDefault, options); CompilationRequestResult r = null; try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories(), DebugContext.DEFAULT_LOG_STREAM); Activation a = debug.activate()) { @@ -187,7 +188,7 @@ public CompilationResult compileHelper(CompilationResultBuilderFactory crbf, CompilationResult result, StructuredGraph graph, ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, boolean shouldRetainLocalVariables, OptionValues options) { - + assert options == graph.getOptions(); HotSpotBackend backend = graalRuntime.getHostBackend(); HotSpotProviders providers = backend.getProviders(); final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; @@ -218,15 +219,11 @@ return result; } - public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { - return compile(method, entryBCI, useProfilingInfo, false, compilationId, options, debug); - } - - public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, boolean shouldRetainLocalVariables, CompilationIdentifier compilationId, OptionValues options, + public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, boolean shouldRetainLocalVariables, CompilationIdentifier compilationId, DebugContext debug) { - StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug); + StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, debug.getOptions(), debug); CompilationResult result = new CompilationResult(compilationId); - return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, options); + return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, debug.getOptions()); } protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo, OptionValues options) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -26,7 +26,9 @@ import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; -import static org.graalvm.compiler.replacements.ReplacementsImpl.Options.UseEncodedSnippets; +import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; +import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; +import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import java.util.Set; @@ -43,6 +45,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.options.OptionValues; @@ -59,12 +62,12 @@ * them. */ public class HotSpotReplacementsImpl extends ReplacementsImpl { - public HotSpotReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { - super(options, new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target); + public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { + super(new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target); } - protected HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) { - super(replacements.options, new GraalDebugHandlersFactory(replacements.snippetReflection), providers, replacements.snippetReflection, + HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) { + super(new GraalDebugHandlersFactory(replacements.snippetReflection), providers, replacements.snippetReflection, replacements.getDefaultReplacementBytecodeProvider(), replacements.target); } @@ -73,14 +76,15 @@ return method.getAnnotation(HotSpotOperation.class) != null ? HotSpotWordOperationPlugin.class : super.getIntrinsifyingPlugin(method); } - public void registerMethodSubstitution(ResolvedJavaMethod method, ResolvedJavaMethod original) { + @Override + public void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { if (!IS_IN_NATIVE_IMAGE) { - if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) { + if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { synchronized (HotSpotReplacementsImpl.class) { if (snippetEncoder == null) { snippetEncoder = new SymbolicSnippetEncoder(this); } - snippetEncoder.registerMethodSubstitution(method, original); + snippetEncoder.registerMethodSubstitution(plugin, original, context, options); } } } @@ -88,12 +92,18 @@ @Override public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug) { - if (IS_IN_NATIVE_IMAGE) { + boolean useEncodedGraphs = UseEncodedGraphs.getValue(debug.getOptions()); + if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) { HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); InvocationPlugin plugin = replacements.getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(method); if (plugin instanceof MethodSubstitutionPlugin) { MethodSubstitutionPlugin msp = (MethodSubstitutionPlugin) plugin; - return replacements.getMethodSubstitution(msp, method); + if (useEncodedGraphs) { + replacements.registerMethodSubstitution(msp, method, ROOT_COMPILATION, debug.getOptions()); + } + StructuredGraph methodSubstitution = replacements.getMethodSubstitution(msp, method, ROOT_COMPILATION, StructuredGraph.AllowAssumptions.YES, debug.getOptions()); + methodSubstitution.resetDebug(debug); + return methodSubstitution; } return null; } @@ -101,6 +111,26 @@ } @Override + public StructuredGraph getSubstitution(ResolvedJavaMethod targetMethod, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { + boolean useEncodedGraphs = UseEncodedGraphs.getValue(options); + if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) { + InvocationPlugin plugin = getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(targetMethod); + if (plugin instanceof MethodSubstitutionPlugin && (!plugin.inlineOnly() || invokeBci >= 0)) { + MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; + if (!IS_IN_NATIVE_IMAGE && useEncodedGraphs) { + registerMethodSubstitution(msPlugin, targetMethod, INLINE_AFTER_PARSING, options); + } + // This assumes the normal path creates the graph using + // GraphBuilderConfiguration.getSnippetDefault with omits exception edges + StructuredGraph subst = getMethodSubstitution(msPlugin, targetMethod, INLINE_AFTER_PARSING, StructuredGraph.AllowAssumptions.NO, options); + return subst; + } + } + + return super.getSubstitution(targetMethod, invokeBci, trackNodeSourcePosition, replaceePosition, options); + } + + @Override public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { if (b.parsingIntrinsic() && snippetEncoder != null) { if (getIntrinsifyingPlugin(method) != null) { @@ -118,16 +148,16 @@ private boolean snippetRegistrationClosed; @Override - public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { + public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { if (!IS_IN_NATIVE_IMAGE) { assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); assert registeredSnippets.add(method) : "Cannot register snippet twice: " + method.format("%H.%n(%p)"); - if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) { + if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { synchronized (HotSpotReplacementsImpl.class) { if (snippetEncoder == null) { snippetEncoder = new SymbolicSnippetEncoder(this); } - snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); + snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition, options); } } } @@ -138,7 +168,7 @@ snippetRegistrationClosed = true; } - static SymbolicSnippetEncoder.EncodedSnippets getEncodedSnippets() { + private static SymbolicSnippetEncoder.EncodedSnippets getEncodedSnippets() { return encodedSnippets; } @@ -153,57 +183,66 @@ HotSpotReplacementsImpl.encodedSnippets = encodedSnippets; } - public boolean encode() { + public boolean encode(OptionValues options) { SymbolicSnippetEncoder encoder = HotSpotReplacementsImpl.snippetEncoder; if (encoder != null) { - return encoder.encode(); + return encoder.encode(options); } return false; } private static volatile SymbolicSnippetEncoder.EncodedSnippets encodedSnippets; - @NativeImageReinitialize static SymbolicSnippetEncoder snippetEncoder; + @NativeImageReinitialize private static SymbolicSnippetEncoder snippetEncoder; @Override - public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { - StructuredGraph graph = getEncodedSnippet(method, args); + public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, + OptionValues options) { + StructuredGraph graph = getEncodedSnippet(method, args, StructuredGraph.AllowAssumptions.NO, options); if (graph != null) { return graph; } assert !IS_IN_NATIVE_IMAGE : "should be using encoded snippets"; - return super.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition); + return super.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition, options); } - public StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, Object[] args) { - if (IS_IN_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) { + private StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { + boolean useEncodedGraphs = UseEncodedGraphs.getValue(options); + if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) { synchronized (HotSpotReplacementsImpl.class) { - if (!IS_IN_NATIVE_IMAGE && UseEncodedSnippets.getValue(options)) { - snippetEncoder.encode(); + if (!IS_IN_NATIVE_IMAGE) { + snippetEncoder.encode(options); } if (getEncodedSnippets() == null) { throw GraalError.shouldNotReachHere("encoded snippets not found"); } - StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args); + StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args, allowAssumptions, options); if (graph == null) { throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); } return graph; } - } else if (registeredSnippets != null) { - assert registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)"); + } else { + assert registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)"); } return null; } - public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original) { - if (IS_IN_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) { + @Override + public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, + StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { + boolean useEncodedGraphs = UseEncodedGraphs.getValue(options); + if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) { + if (!IS_IN_NATIVE_IMAGE) { + snippetEncoder.encode(options); + } + if (getEncodedSnippets() == null) { throw GraalError.shouldNotReachHere("encoded snippets not found"); } - return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this); + return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this, context, allowAssumptions, options); } return null; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java 2019-04-24 19:25:41.000000000 +0000 @@ -63,4 +63,9 @@ Module module = declaringClass.getModule(); return jvmciModule == module || graalModule == module || compilerConfigurationModule == module; } + + @Override + HotSpotJVMCICompilerFactory.CompilationLevelAdjustment getCompilationLevelAdjustment() { + return HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.ByHolder; + } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java 2019-04-24 19:25:41.000000000 +0000 @@ -161,7 +161,7 @@ import org.graalvm.compiler.replacements.DefaultJavaLoweringProvider; import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode; import org.graalvm.compiler.replacements.arraycopy.ArrayCopySnippets; -import org.graalvm.compiler.replacements.arraycopy.ArrayCopyWithSlowPathNode; +import org.graalvm.compiler.replacements.arraycopy.ArrayCopyWithDelayedLoweringNode; import org.graalvm.compiler.replacements.nodes.AssertionNode; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import jdk.internal.vm.compiler.word.LocationIdentity; @@ -234,6 +234,10 @@ foreignCallSnippets = new ForeignCallSnippets.Templates(options, factories, providers, target); } + public ArrayCopySnippets.Templates getArraycopySnippets() { + return arraycopySnippets; + } + public MonitorSnippets.Templates getMonitorSnippets() { return monitorSnippets; } @@ -332,8 +336,8 @@ } } else if (n instanceof ArrayCopyNode) { arraycopySnippets.lower((ArrayCopyNode) n, tool); - } else if (n instanceof ArrayCopyWithSlowPathNode) { - arraycopySnippets.lower((ArrayCopyWithSlowPathNode) n, tool); + } else if (n instanceof ArrayCopyWithDelayedLoweringNode) { + arraycopySnippets.lower((ArrayCopyWithDelayedLoweringNode) n, tool); } else if (n instanceof G1PreWriteBarrier) { writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool); } else if (n instanceof G1PostWriteBarrier) { @@ -468,11 +472,15 @@ if (invoke.callTarget() instanceof MethodCallTargetNode) { MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); NodeInputList parameters = callTarget.arguments(); - ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); - if (!callTarget.isStatic() && receiver.stamp(NodeView.DEFAULT) instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { - ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool); - parameters.set(0, nonNullReceiver); - receiver = nonNullReceiver; + ValueNode receiver = parameters.isEmpty() ? null : parameters.get(0); + + if (!callTarget.isStatic()) { + assert receiver != null : "non-static call must have a receiver"; + if (receiver.stamp(NodeView.DEFAULT) instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { + ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool); + parameters.set(0, nonNullReceiver); + receiver = nonNullReceiver; + } } JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java 2019-04-24 19:25:41.000000000 +0000 @@ -24,13 +24,11 @@ package org.graalvm.compiler.hotspot.meta; -import java.lang.reflect.Method; import java.util.function.Supplier; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; import org.graalvm.compiler.nodes.ConstantNode; @@ -40,6 +38,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import jdk.vm.ci.hotspot.HotSpotConstantPool; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -85,44 +84,17 @@ return false; } - private static final Class hscp; - private static final Method loadReferencedTypeIIZMH; - - static { - Method m = null; - Class c = null; - try { - c = Class.forName("jdk.vm.ci.hotspot.HotSpotConstantPool").asSubclass(ConstantPool.class); - m = c.getDeclaredMethod("loadReferencedType", int.class, int.class, boolean.class); - } catch (Exception e) { - throw GraalError.shouldNotReachHere(e); - } - loadReferencedTypeIIZMH = m; - hscp = c; - } - - private static boolean isHotSpotConstantPool(ConstantPool cp) { - // jdk.vm.ci.hotspot.HotSpotConstantPool is final, so we can - // directly compare Classes. - return cp.getClass() == hscp; - } - @Override public boolean supportsLazyInitialization(ConstantPool cp) { - if (loadReferencedTypeIIZMH != null && isHotSpotConstantPool(cp)) { - return true; - } - return false; + // jdk.vm.ci.hotspot.HotSpotConstantPool is final, so we can + // directly compare Classes. + return (cp instanceof HotSpotConstantPool); } @Override public void loadReferencedType(GraphBuilderContext builder, ConstantPool cp, int cpi, int opcode) { - if (loadReferencedTypeIIZMH != null && isHotSpotConstantPool(cp)) { - try { - loadReferencedTypeIIZMH.invoke(cp, cpi, opcode, false); - } catch (Throwable t) { - throw GraalError.shouldNotReachHere(t); - } + if (cp instanceof HotSpotConstantPool) { + ((HotSpotConstantPool) cp).loadReferencedType(cpi, opcode, false); } else { cp.loadReferencedType(cpi, opcode); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -35,6 +35,7 @@ import jdk.internal.vm.compiler.collections.EconomicMap; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect; @@ -207,11 +208,19 @@ public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { assert foreignCalls != null : descriptor; HotSpotForeignCallLinkage callTarget = foreignCalls.get(descriptor); + if (callTarget == null) { + throw GraalError.shouldNotReachHere("missing implementation for runtime call: " + descriptor); + } callTarget.finalizeAddress(runtime.getHostBackend()); return callTarget; } @Override + public boolean isAvailable(ForeignCallDescriptor descriptor) { + return foreignCalls.containsKey(descriptor); + } + + @Override public boolean isReexecutable(ForeignCallDescriptor descriptor) { assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor; return foreignCalls.get(descriptor).isReexecutable(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot.meta; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.hotspot.HotSpotBackend.BASE64_ENCODE_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.GHASH_PROCESS_BLOCKS; import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION; @@ -123,9 +124,11 @@ * @param constantReflection * @param snippetReflection * @param foreignCalls + * @param options */ public static Plugins create(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, - ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, ReplacementsImpl replacements) { + ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, ReplacementsImpl replacements, + OptionValues options) { InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, compilerConfiguration); Plugins plugins = new Plugins(invocationPlugins); @@ -135,7 +138,6 @@ plugins.appendTypePlugin(nodePlugin); plugins.appendNodePlugin(nodePlugin); - OptionValues options = replacements.getOptions(); if (!GeneratePIC.getValue(options)) { plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), true)); } @@ -172,6 +174,7 @@ registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider); registerGHASHPlugins(invocationPlugins, config, metaAccess, foreignCalls); registerCounterModePlugins(invocationPlugins, config, replacementBytecodeProvider); + registerBase64Plugins(invocationPlugins, config, metaAccess, foreignCalls); registerUnsafePlugins(invocationPlugins, replacementBytecodeProvider); StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacementBytecodeProvider, true, false); registerArrayPlugins(invocationPlugins, replacementBytecodeProvider); @@ -563,6 +566,38 @@ } } + private static void registerBase64Plugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) { + if (config.useBase64Intrinsics()) { + Registration r = new Registration(plugins, "java.util.Base64$Encoder"); + r.register7("encodeBlock", + Receiver.class, + byte[].class, + int.class, + int.class, + byte[].class, + int.class, + boolean.class, + new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, + ResolvedJavaMethod targetMethod, + Receiver receiver, + ValueNode src, + ValueNode sp, + ValueNode sl, + ValueNode dst, + ValueNode dp, + ValueNode isURL) { + int byteArrayBaseOffset = metaAccess.getArrayBaseOffset(JavaKind.Byte); + ComputeObjectAddressNode srcAddress = b.add(new ComputeObjectAddressNode(src, ConstantNode.forInt(byteArrayBaseOffset))); + ComputeObjectAddressNode dstAddress = b.add(new ComputeObjectAddressNode(dst, ConstantNode.forInt(byteArrayBaseOffset))); + b.add(new ForeignCallNode(foreignCalls, BASE64_ENCODE_BLOCK, srcAddress, sp, sl, dstAddress, dp, isURL)); + return true; + } + }); + } + } + private static void registerCRC32Plugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { if (config.useCRC32Intrinsics) { Registration r = new Registration(plugins, CRC32.class, bytecodeProvider); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java 2019-04-24 19:25:41.000000000 +0000 @@ -29,6 +29,7 @@ import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM; import static org.graalvm.compiler.hotspot.HotSpotBackend.BACKEDGE_EVENT; +import static org.graalvm.compiler.hotspot.HotSpotBackend.BASE64_ENCODE_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.COUNTERMODE_IMPL_CRYPT; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK; @@ -72,7 +73,7 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.STACK_INSPECTABLE_LEAF; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER; @@ -217,7 +218,7 @@ String name = kind + (aligned ? "Aligned" : "") + (disjoint ? "Disjoint" : "") + (uninit ? "Uninit" : "") + "Arraycopy" + (killAny ? "KillAny" : ""); ForeignCallDescriptor desc = new ForeignCallDescriptor(name, void.class, Word.class, Word.class, Word.class); LocationIdentity killed = killAny ? LocationIdentity.any() : NamedLocationIdentity.getArrayLocation(kind); - registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, NOT_REEXECUTABLE, killed); return desc; } @@ -232,7 +233,7 @@ // return: 0 = success, n = number of copied elements xor'd with -1. ForeignCallDescriptor desc = new ForeignCallDescriptor(name, int.class, Word.class, Word.class, Word.class, Word.class, Word.class); LocationIdentity killed = NamedLocationIdentity.any(); - registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, NOT_REEXECUTABLE, killed); checkcastArraycopyDescriptors[uninit ? 1 : 0] = desc; } @@ -272,25 +273,25 @@ public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig c = runtime.getVMConfig(); - registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); if (c.enableStackReservedZoneAddress != 0) { assert c.throwDelayedStackOverflowErrorEntry != 0 : "both must exist"; - registerForeignCall(ENABLE_STACK_RESERVED_ZONE, c.enableStackReservedZoneAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(THROW_DELAYED_STACKOVERFLOW_ERROR, c.throwDelayedStackOverflowErrorEntry, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(ENABLE_STACK_RESERVED_ZONE, c.enableStackReservedZoneAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(THROW_DELAYED_STACKOVERFLOW_ERROR, c.throwDelayedStackOverflowErrorEntry, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); } - registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); registerMathStubs(c, providers, options); registerForeignCall(ARITHMETIC_FREM, c.fremAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(ARITHMETIC_DREM, c.dremAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); + registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); @@ -318,7 +319,7 @@ link(new ExceptionHandlerStub(options, providers, foreignCalls.get(EXCEPTION_HANDLER))); link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()))); - link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS))); + link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS))); EnumMap exceptionRuntimeCalls = DefaultHotSpotLoweringProvider.RuntimeCalls.runtimeCalls; link(new ArrayStoreExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.ARRAY_STORE), SAFEPOINT, REEXECUTABLE, any()))); @@ -338,14 +339,14 @@ linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(options, providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NO_LOCATIONS); - linkForeignCall(options, providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NO_LOCATIONS); + linkForeignCall(options, providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); if (GeneratePIC.getValue(options)) { - registerForeignCall(WRONG_METHOD_HANDLER, c.handleWrongMethodStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(WRONG_METHOD_HANDLER, c.handleWrongMethodStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS); CompilerRuntimeHotSpotVMConfig cr = new CompilerRuntimeHotSpotVMConfig(HotSpotJVMCIRuntime.runtime().getConfigStore()); linkForeignCall(options, providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION); linkForeignCall(options, providers, RESOLVE_DYNAMIC_INVOKE, cr.resolveDynamicInvoke, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); @@ -375,11 +376,11 @@ registerCheckcastArraycopyDescriptor(true, c.checkcastArraycopyUninit); registerCheckcastArraycopyDescriptor(false, c.checkcastArraycopy); - registerForeignCall(GENERIC_ARRAYCOPY, c.genericArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any()); - registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any()); + registerForeignCall(GENERIC_ARRAYCOPY, c.genericArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any()); + registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any()); if (c.useMultiplyToLenIntrinsic()) { - registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, + registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int)); } @@ -398,19 +399,22 @@ if (c.useGHASHIntrinsics()) { registerForeignCall(GHASH_PROCESS_BLOCKS, c.ghashProcessBlocks, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any()); } + if (c.useBase64Intrinsics()) { + registerForeignCall(BASE64_ENCODE_BLOCK, c.base64EncodeBlock, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any()); + } if (c.useMulAddIntrinsic()) { - registerForeignCall(MUL_ADD, c.mulAdd, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int)); + registerForeignCall(MUL_ADD, c.mulAdd, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int)); } if (c.useMontgomeryMultiplyIntrinsic()) { - registerForeignCall(MONTGOMERY_MULTIPLY, c.montgomeryMultiply, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, + registerForeignCall(MONTGOMERY_MULTIPLY, c.montgomeryMultiply, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int)); } if (c.useMontgomerySquareIntrinsic()) { - registerForeignCall(MONTGOMERY_SQUARE, c.montgomerySquare, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, + registerForeignCall(MONTGOMERY_SQUARE, c.montgomerySquare, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int)); } if (c.useSquareToLenIntrinsic()) { - registerForeignCall(SQUARE_TO_LEN, c.squareToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int)); + registerForeignCall(SQUARE_TO_LEN, c.squareToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int)); } if (c.useAESIntrinsics) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java 2019-04-24 19:25:41.000000000 +0000 @@ -65,8 +65,9 @@ } @Override - public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) { - final boolean isTracing = GraalOptions.TraceInlining.getValue(replacements.getOptions()); + public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) { + OptionValues options = calleeInfo.graph().getOptions(); + final boolean isTracing = GraalOptions.TraceInlining.getValue(options); final InlineInfo info = invocation.callee(); for (int i = 0; i < info.numberOfMethods(); ++i) { @@ -79,7 +80,6 @@ final double probability = invocation.probability(); final double relevance = invocation.relevance(); - OptionValues options = info.graph().getOptions(); if (InlineEverything.getValue(options)) { InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything"); return InliningPolicy.Decision.YES.withReason(isTracing, "inline everything"); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java 2019-04-24 19:25:41.000000000 +0000 @@ -160,7 +160,7 @@ return field.getOffset(); } } - throw new GraalError("missing field " + fieldName); + throw new GraalError("missing field " + fieldName + " in type " + type); } public static HotSpotJVMCIRuntime runtime() { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java 2019-04-24 19:25:41.000000000 +0000 @@ -831,7 +831,8 @@ invoke.setStateAfter(graph.start().stateAfter()); graph.addAfterFixed(graph.start(), invoke); - StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null, invoke.graph().trackNodeSourcePosition(), invoke.getNodeSourcePosition()); + StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null, null, invoke.graph().trackNodeSourcePosition(), invoke.getNodeSourcePosition(), + invoke.getOptions()); InliningUtil.inline(invoke, inlineeGraph, false, null); List rets = graph.getNodes(ReturnNode.TYPE).snapshot(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -89,7 +89,7 @@ StructuredGraph snippetGraph = null; DebugContext debug = getDebug(); try (DebugContext.Scope s = debug.scope("ArrayCloneSnippet", snippetMethod)) { - snippetGraph = replacements.getSnippet(snippetMethod, null, graph().trackNodeSourcePosition(), this.getNodeSourcePosition()); + snippetGraph = replacements.getSnippet(snippetMethod, null, null, graph().trackNodeSourcePosition(), this.getNodeSourcePosition(), debug.getOptions()); } catch (Throwable e) { throw debug.handle(e); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java 2019-04-24 19:25:41.000000000 +0000 @@ -84,7 +84,7 @@ } protected void registerSnippet() { - providers.getReplacements().registerSnippet(method, null, null, false); + providers.getReplacements().registerSnippet(method, null, null, false, options); } @Override @@ -115,7 +115,7 @@ } protected StructuredGraph buildInitialGraph(DebugContext debug, CompilationIdentifier compilationId, Object[] args) { - return providers.getReplacements().getSnippet(method, args, false, null).copyWithIdentifier(compilationId, debug); + return providers.getReplacements().getSnippet(method, null, args, false, null, options).copyWithIdentifier(compilationId, debug); } protected boolean checkConstArg(int index, String expectedName) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java 2019-04-24 19:25:41.000000000 +0000 @@ -183,7 +183,7 @@ Description description = new Description(linkage, "Stub_" + nextStubId.incrementAndGet()); return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection()))); } - return DebugContext.DISABLED; + return DebugContext.disabled(options); } /** diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java 2019-04-24 19:25:41.000000000 +0000 @@ -27,8 +27,9 @@ import static jdk.vm.ci.runtime.JVMCI.getRuntime; import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; +import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; -import static org.graalvm.compiler.replacements.ReplacementsImpl.Options.UseEncodedSnippets; +import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.util.ArrayList; import java.util.Arrays; @@ -48,6 +49,7 @@ import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; import org.graalvm.compiler.api.runtime.GraalRuntime; import org.graalvm.compiler.bytecode.BytecodeProvider; +import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampPair; @@ -86,7 +88,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.nodes.java.AccessFieldNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; -import org.graalvm.compiler.nodes.spi.DelegatingReplacements; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; @@ -98,12 +99,12 @@ import org.graalvm.compiler.replacements.SnippetCounter; import org.graalvm.compiler.replacements.SnippetIntegerHistogram; -import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; +import jdk.vm.ci.hotspot.HotSpotSignature; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; @@ -123,13 +124,13 @@ * method references into a symbolic form that can be resolved at graph decode time using * {@link SymbolicJVMCIReference}. */ -public class SymbolicSnippetEncoder extends DelegatingReplacements { +public class SymbolicSnippetEncoder { /** * This is a customized HotSpotReplacementsImpl intended only for parsing snippets and method * substitutions for graph encoding. */ - private final HotSpotSnippetReplacementsImpl replacements; + private final HotSpotSnippetReplacementsImpl snippetReplacements; /** * The set of all snippet methods that have been encoded. @@ -142,11 +143,13 @@ */ private final Map originalMethods = new ConcurrentHashMap<>(); + private final HotSpotReplacementsImpl originalReplacements; + /** * The current count of graphs encoded. Used to detect when new graphs have been enqueued for * encoding. */ - int encodedGraphs = 0; + private int encodedGraphs = 0; /** * All the graphs parsed so far. @@ -175,13 +178,13 @@ return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION; } - if (getIntrinsifyingPlugin(method) != null) { + if (snippetReplacements.getIntrinsifyingPlugin(method) != null) { delayedInvocationPluginMethods.add(method); return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION; } // Force inlining when parsing replacements - return createIntrinsicInlineInfo(method, null, getDefaultReplacementBytecodeProvider()); + return createIntrinsicInlineInfo(method, snippetReplacements.getDefaultReplacementBytecodeProvider()); } @Override @@ -219,12 +222,12 @@ return true; } if (field.getType().getName().equals(snippetCounterName)) { - b.addPush(JavaKind.Object, ConstantNode.forConstant(replacements.snippetReflection.forObject(SnippetCounter.DISABLED_COUNTER), b.getMetaAccess())); + b.addPush(JavaKind.Object, ConstantNode.forConstant(snippetReplacements.snippetReflection.forObject(SnippetCounter.DISABLED_COUNTER), b.getMetaAccess())); return true; } if (field.getType().getName().equals(snippetIntegerHistogramName)) { - b.addPush(JavaKind.Object, ConstantNode.forConstant(replacements.snippetReflection.forObject(SnippetIntegerHistogram.DISABLED_COUNTER), b.getMetaAccess())); + b.addPush(JavaKind.Object, ConstantNode.forConstant(snippetReplacements.snippetReflection.forObject(SnippetIntegerHistogram.DISABLED_COUNTER), b.getMetaAccess())); return true; } return false; @@ -240,8 +243,7 @@ } SymbolicSnippetEncoder(HotSpotReplacementsImpl replacements) { - super(replacements); - + this.originalReplacements = replacements; GraphBuilderConfiguration.Plugins plugins = replacements.getGraphBuilderPlugins(); SnippetInvocationPlugins invocationPlugins = new SnippetInvocationPlugins(plugins.getInvocationPlugins()); GraphBuilderConfiguration.Plugins copy = new GraphBuilderConfiguration.Plugins(plugins, invocationPlugins); @@ -249,22 +251,20 @@ copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin()); copy.appendNodePlugin(new SnippetCounterPlugin()); HotSpotProviders providers = (HotSpotProviders) replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection())); - this.replacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy)); - this.replacements.setGraphBuilderPlugins(copy); - } - - @Override - public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() { - return replacements.getGraphBuilderPlugins(); + this.snippetReplacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy)); + this.snippetReplacements.setGraphBuilderPlugins(copy); } /** * Compiles the snippet and stores the graph. */ - public void registerMethodSubstitution(ResolvedJavaMethod method, ResolvedJavaMethod original) { + synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { + ResolvedJavaMethod method = plugin.getSubstitute(snippetReplacements.getProviders().getMetaAccess()); assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName(); - buildGraph(method, original, null, false, false); + StructuredGraph subst = buildGraph(method, original, null, true, false, context, options); snippetMethods.add(method); + originalMethods.put(methodKey(method), methodKey(original)); + preparedSnippetGraphs.put(plugin.toString() + context, subst); } static class EncodedSnippets { @@ -282,54 +282,26 @@ this.originalMethods = originalMethods; } - public StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, ReplacementsImpl replacements) { - Integer startOffset = snippetStartOffsets.get(plugin.toString()); + StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, ReplacementsImpl replacements, IntrinsicContext.CompilationContext context, + StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { + Integer startOffset = snippetStartOffsets.get(plugin.toString() + context); if (startOffset == null) { - throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin); + throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin + " with " + context); } - return decodeGraph(original, null, startOffset, replacements); + ResolvedJavaType accessingClass = replacements.getProviders().getMetaAccess().lookupJavaType(plugin.getDeclaringClass()); + return decodeGraph(original, accessingClass, startOffset, replacements, context, allowAssumptions, options); } @SuppressWarnings("try") - private StructuredGraph decodeGraph(ResolvedJavaMethod method, Object[] args, int startOffset, ReplacementsImpl replacements) { - OptionValues options = replacements.getOptions(); - SnippetReflectionProvider snippetReflection = replacements.snippetReflection; - ParameterPlugin parameterPlugin = null; + private StructuredGraph decodeGraph(ResolvedJavaMethod method, ResolvedJavaType accessingClass, int startOffset, ReplacementsImpl replacements, + IntrinsicContext.CompilationContext context, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { Providers providers = replacements.getProviders(); - if (args != null) { - parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), snippetReflection); - } - - EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, method.getDeclaringClass(), - originalMethods.get(methodKey(method))); - try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method)) { - StructuredGraph result = new StructuredGraph.Builder(options, debug).method(method).setIsSubstitution(true).build(); - PEGraphDecoder graphDecoder = new PEGraphDecoder( - providers.getCodeCache().getTarget().arch, - result, - providers, - null, // loopExplosionPlugin - replacements.getGraphBuilderPlugins().getInvocationPlugins(), - new InlineInvokePlugin[0], - parameterPlugin, - null, // nodePlugins - null, // callInlinedMethod - null // sourceLanguagePositionProvider - ) { - @Override - protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod, - ResolvedJavaMethod originalMethod, - BytecodeProvider intrinsicBytecodeProvider, - boolean isSubstitution, - boolean trackNodeSourcePosition) { - if (lookupMethod.equals(method)) { - return encodedGraph; - } else { - throw GraalError.shouldNotReachHere(method.format("%H.%n(%p)")); - } - } - }; + EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, + methodKey(method), accessingClass, method.getDeclaringClass()); + try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) { + StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions).method(method).setIsSubstitution(true).build(); + PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, null, method, context, encodedGraph); graphDecoder.decode(method, result.isSubstitution(), encodedGraph.trackNodeSourcePosition()); @@ -338,7 +310,7 @@ } } - StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args) { + StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { Integer startOffset = null; if (snippetStartOffsets != null) { startOffset = snippetStartOffsets.get(methodKey(method)); @@ -351,22 +323,57 @@ } } - SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, method.getDeclaringClass(), - originalMethods.get(methodKey(method))); - return decodeSnippetGraph(encodedGraph, method, replacements, args, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch); + SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, + originalMethods.get(methodKey(method)), method.getDeclaringClass()); + return decodeSnippetGraph(encodedGraph, method, replacements, args, allowAssumptions, options); } } - private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition) { + private static class SubstitutionGraphDecoder extends PEGraphDecoder { + private final ResolvedJavaMethod method; + private final EncodedGraph encodedGraph; + private IntrinsicContext intrinsic; + + SubstitutionGraphDecoder(Providers providers, StructuredGraph result, ReplacementsImpl replacements, ParameterPlugin parameterPlugin, ResolvedJavaMethod method, + IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph) { + super(providers.getCodeCache().getTarget().arch, result, providers, null, + replacements.getGraphBuilderPlugins().getInvocationPlugins(), new InlineInvokePlugin[0], parameterPlugin, + null, null, null); + this.method = method; + this.encodedGraph = encodedGraph; + intrinsic = new IntrinsicContext(method, null, replacements.getDefaultReplacementBytecodeProvider(), context, false); + } + + @Override + protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod, + MethodSubstitutionPlugin plugin, + BytecodeProvider intrinsicBytecodeProvider, + boolean isSubstitution, + boolean trackNodeSourcePosition) { + if (lookupMethod.equals(method)) { + return encodedGraph; + } else { + throw GraalError.shouldNotReachHere(method.format("%H.%n(%p)")); + } + } + + @Override + protected IntrinsicContext getIntrinsic() { + return intrinsic; + } + } + + private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition, + IntrinsicContext.CompilationContext context, OptionValues options) { assert method.hasBytecodes() : "Snippet must not be abstract or native"; Object[] args = null; if (receiver != null) { args = new Object[method.getSignature().getParameterCount(true)]; args[0] = receiver; } - try (DebugContext debug = openDebugContext("Snippet_", method)) { - StructuredGraph graph = replacements.makeGraph(debug, replacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null); + try (DebugContext debug = openDebugContext("Snippet_", method, options)) { + StructuredGraph graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null, context); // Check if all methods which should be inlined are really inlined. for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { @@ -382,48 +389,24 @@ } @SuppressWarnings("try") - static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args, Architecture architecture) { + private static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args, + StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { Providers providers = replacements.getProviders(); ParameterPlugin parameterPlugin = null; if (args != null) { parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), replacements.snippetReflection); } - try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method)) { + try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) { // @formatter:off - StructuredGraph result = new StructuredGraph.Builder(replacements.getOptions(), debug) - .method(method) - .trackNodeSourcePosition(encodedGraph.trackNodeSourcePosition()) - .setIsSubstitution(true) - .build(); + StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions) + .method(method) + .trackNodeSourcePosition(encodedGraph.trackNodeSourcePosition()) + .setIsSubstitution(true) + .build(); // @formatter:on try (DebugContext.Scope scope = debug.scope("DecodeSnippetGraph", result)) { - PEGraphDecoder graphDecoder = new PEGraphDecoder( - architecture, - result, - providers, - null, - replacements.getGraphBuilderPlugins().getInvocationPlugins(), - new InlineInvokePlugin[0], - parameterPlugin, - null, - null, - null) { - @Override - protected EncodedGraph lookupEncodedGraph( - ResolvedJavaMethod lookupMethod, - ResolvedJavaMethod originalMethod, - BytecodeProvider intrinsicBytecodeProvider, - boolean isSubstitution, - boolean track) { - if (lookupMethod.equals(method)) { - assert !track || encodedGraph.trackNodeSourcePosition(); - return encodedGraph; - } else { - throw GraalError.shouldNotReachHere(method.format("%H.%n(%p)")); - } - } - }; + PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph); graphDecoder.decode(method, result.isSubstitution(), encodedGraph.trackNodeSourcePosition()); debug.dump(DebugContext.VERBOSE_LEVEL, result, "After decoding"); @@ -437,14 +420,12 @@ } @SuppressWarnings("try") - private boolean verifySnippetEncodeDecode(ResolvedJavaMethod method, ResolvedJavaMethod original, boolean trackNodeSourcePosition, StructuredGraph structuredGraph) { + private boolean verifySnippetEncodeDecode(ResolvedJavaMethod method, ResolvedJavaMethod original, boolean trackNodeSourcePosition, StructuredGraph graph) { // Verify the encoding and decoding process - EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(structuredGraph, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch); + EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch); - Architecture arch = HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch; - - try (DebugContext debug = replacements.openDebugContext("VerifySnippetEncodeDecode_", method)) { - HotSpotProviders originalProvider = (HotSpotProviders) replacements.getProviders(); + try (DebugContext debug = snippetReplacements.openDebugContext("VerifySnippetEncodeDecode_", method, graph.getOptions())) { + HotSpotProviders originalProvider = (HotSpotProviders) snippetReplacements.getProviders(); SnippetReflectionProvider snippetReflection = originalProvider.getSnippetReflection(); SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider constantReflection = new SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider( @@ -452,29 +433,29 @@ HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection, originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins()); - HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(getOptions(), newProviders, snippetReflection, - originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), - originalProvider.getCodeCache().getTarget()); + HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection, + originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins()); - try (DebugContext.Scope scaope = debug.scope("VerifySnippetEncodeDecode", structuredGraph)) { + try (DebugContext.Scope scaope = debug.scope("VerifySnippetEncodeDecode", graph)) { for (int i = 0; i < encodedGraph.getNumObjects(); i++) { filterSnippetObject(encodedGraph.getObject(i)); } StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, null, original, trackNodeSourcePosition, null); SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), original != null ? methodKey(original) : null); - StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, method, replacements, null, arch); + StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null, + StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions()); String snippetString = getCanonicalGraphString(snippet, true, false); String decodedSnippetString = getCanonicalGraphString(decodedSnippet, true, false); if (snippetString.equals(decodedSnippetString)) { debug.log("Snippet decode for %s produces exactly same graph", method); - debug.dump(DebugContext.INFO_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); + debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); } else { debug.log("Snippet decode for %s produces different graph", method); debug.log("%s", compareGraphStrings(snippet, snippetString, decodedSnippet, decodedSnippetString)); - debug.dump(DebugContext.INFO_LEVEL, snippet, "Snippet graph for %s", method); - debug.dump(DebugContext.INFO_LEVEL, structuredGraph, "Encoded snippet graph for %s", method); - debug.dump(DebugContext.INFO_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); + debug.dump(DebugContext.VERBOSE_LEVEL, snippet, "Snippet graph for %s", method); + debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Encoded snippet graph for %s", method); + debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); } } catch (Throwable t) { throw debug.handle(t); @@ -487,10 +468,10 @@ * If there are new graphs waiting to be encoded, reencode all the graphs and return the result. */ @SuppressWarnings("try") - synchronized EncodedSnippets maybeEncodeSnippets() { + private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) { Map graphs = this.preparedSnippetGraphs; if (encodedGraphs != graphs.size()) { - DebugContext debug = openDebugContext("SnippetEncoder", null); + DebugContext debug = openDebugContext("SnippetEncoder", null, options); try (DebugContext.Scope scope = debug.scope("SnippetSupportEncode")) { encodedGraphs = graphs.size(); for (StructuredGraph graph : graphs.values()) { @@ -504,23 +485,23 @@ return null; } - @Override - public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { - if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(getOptions())) { + synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { + if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); String key = methodKey(method); if (!preparedSnippetGraphs.containsKey(key)) { if (original != null) { originalMethods.put(key, methodKey(original)); } - StructuredGraph snippet = buildGraph(method, original, receiver, true, trackNodeSourcePosition); + StructuredGraph snippet = buildGraph(method, original, receiver, true, trackNodeSourcePosition, INLINE_AFTER_PARSING, options); snippetMethods.add(method); preparedSnippetGraphs.put(key, snippet); } } + } - EncodedSnippets encodeSnippets(DebugContext debug) { + private synchronized EncodedSnippets encodeSnippets(DebugContext debug) { GraphEncoder encoder = new GraphEncoder(HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch, debug); for (StructuredGraph graph : preparedSnippetGraphs.values()) { encoder.prepare(graph); @@ -552,8 +533,8 @@ * Encode any outstanding graphs and return true if any work was done. */ @SuppressWarnings("try") - public boolean encode() { - EncodedSnippets encodedSnippets = maybeEncodeSnippets(); + public boolean encode(OptionValues options) { + EncodedSnippets encodedSnippets = maybeEncodeSnippets(options); if (encodedSnippets != null) { HotSpotReplacementsImpl.setEncodedSnippets(encodedSnippets); return true; @@ -561,38 +542,65 @@ return false; } - private DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) { - return replacements.openDebugContext(idPrefix, method); + private DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method, OptionValues options) { + return snippetReplacements.openDebugContext(idPrefix, method, options); } static class SymbolicEncodedGraph extends EncodedGraph { - private final ResolvedJavaType accessingClass; + private final ResolvedJavaType[] accessingClasses; private final String originalMethod; - SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass[] types, ResolvedJavaType accessingClass, String originalMethod) { + SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass[] types, String originalMethod, ResolvedJavaType... accessingClasses) { super(encoding, startOffset, objects, types, null, null, null, false, false); - this.accessingClass = accessingClass; + this.accessingClasses = accessingClasses; this.originalMethod = originalMethod; } SymbolicEncodedGraph(EncodedGraph encodedGraph, ResolvedJavaType declaringClass, String originalMethod) { - this(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), encodedGraph.getObjects(), encodedGraph.getNodeClasses(), declaringClass, originalMethod); + this(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), encodedGraph.getObjects(), encodedGraph.getNodeClasses(), + originalMethod, declaringClass); } @Override public Object getObject(int i) { Object o = objects[i]; + Object replacement = null; if (o instanceof SymbolicJVMCIReference) { - objects[i] = o = ((SymbolicJVMCIReference) o).resolve(accessingClass); + for (ResolvedJavaType type : accessingClasses) { + try { + replacement = ((SymbolicJVMCIReference) o).resolve(type); + break; + } catch (NoClassDefFoundError | AssertionError e) { + } + } } else if (o instanceof UnresolvedJavaType) { - objects[i] = o = ((UnresolvedJavaType) o).resolve(accessingClass); + for (ResolvedJavaType type : accessingClasses) { + try { + replacement = ((UnresolvedJavaType) o).resolve(type); + break; + } catch (NoClassDefFoundError | AssertionError e) { + } + } } else if (o instanceof UnresolvedJavaMethod) { throw new InternalError(o.toString()); } else if (o instanceof UnresolvedJavaField) { - objects[i] = o = ((UnresolvedJavaField) o).resolve(accessingClass); + for (ResolvedJavaType type : accessingClasses) { + try { + replacement = ((UnresolvedJavaField) o).resolve(type); + break; + } catch (NoClassDefFoundError | AssertionError e) { + } + } } else if (o instanceof GraalCapability) { - objects[i] = o = ((GraalCapability) o).resolve(((GraalJVMCICompiler) getRuntime().getCompiler()).getGraalRuntime()); + replacement = ((GraalCapability) o).resolve(((GraalJVMCICompiler) getRuntime().getCompiler()).getGraalRuntime()); + } else { + return o; + } + if (replacement != null) { + objects[i] = o = replacement; + } else { + throw new GraalError("Can't resolve " + o); } return o; } @@ -632,7 +640,7 @@ final String methodName; final String signature; - SymbolicResolvedJavaMethod(HotSpotResolvedJavaMethod method) { + SymbolicResolvedJavaMethod(ResolvedJavaMethod method) { this.type = UnresolvedJavaType.create(method.getDeclaringClass().getName()); this.methodName = method.getName(); this.signature = method.getSignature().toMethodDescriptor(); @@ -650,6 +658,9 @@ @Override public ResolvedJavaMethod resolve(ResolvedJavaType accessingClass) { ResolvedJavaType resolvedType = type.resolve(accessingClass); + if (resolvedType == null) { + throw new InternalError("Could not resolve " + this + " in context of " + accessingClass.toJavaName()); + } for (ResolvedJavaMethod method : methodName.equals("") ? resolvedType.getDeclaredConstructors() : resolvedType.getDeclaredMethods()) { if (method.getName().equals(methodName) && method.getSignature().toMethodDescriptor().equals(signature)) { return method; @@ -665,7 +676,7 @@ final UnresolvedJavaType signature; private final boolean isStatic; - SymbolicResolvedJavaField(HotSpotResolvedJavaField field) { + SymbolicResolvedJavaField(ResolvedJavaField field) { this.declaringType = UnresolvedJavaType.create(field.getDeclaringClass().getName()); this.name = field.getName(); this.signature = UnresolvedJavaType.create(field.getType().getName()); @@ -697,6 +708,19 @@ } } + static class SymbolicResolvedJavaMethodBytecode implements SymbolicJVMCIReference { + SymbolicResolvedJavaMethod method; + + SymbolicResolvedJavaMethodBytecode(ResolvedJavaMethodBytecode bytecode) { + method = new SymbolicResolvedJavaMethod(bytecode.getMethod()); + } + + @Override + public ResolvedJavaMethodBytecode resolve(ResolvedJavaType accessingClass) { + return new ResolvedJavaMethodBytecode(method.resolve(accessingClass)); + } + } + static class SymbolicStampPair implements SymbolicJVMCIReference { Object trustedStamp; Object uncheckdStamp; @@ -820,13 +844,13 @@ * Objects embedded in encoded graphs might need to converted into a symbolic form so convert * the object or pass it through. */ - static Object filterSnippetObject(Object o) { + private static Object filterSnippetObject(Object o) { if (o instanceof HotSpotResolvedJavaMethod) { return new SymbolicResolvedJavaMethod((HotSpotResolvedJavaMethod) o); } else if (o instanceof HotSpotResolvedJavaField) { return new SymbolicResolvedJavaField((HotSpotResolvedJavaField) o); } else if (o instanceof HotSpotResolvedJavaType) { - return UnresolvedJavaType.create(((HotSpotResolvedJavaType) o).getName()); + return UnresolvedJavaType.create(((ResolvedJavaType) o).getName()); } else if (o instanceof NodeSourcePosition) { // Filter these out for now. These can't easily be handled because these positions // description snippet methods which might not be available in the runtime. @@ -843,11 +867,15 @@ if (((StampPair) o).getTrustedStamp() instanceof AbstractObjectStamp) { return new SymbolicStampPair((StampPair) o); } + } else if (o instanceof ResolvedJavaMethodBytecode) { + return new SymbolicResolvedJavaMethodBytecode((ResolvedJavaMethodBytecode) o); + } else if (o instanceof HotSpotSignature) { + throw new GraalError(o.toString()); } return o; } - static String compareGraphStrings(StructuredGraph expectedGraph, String expectedString, StructuredGraph actualGraph, String actualString) { + private static String compareGraphStrings(StructuredGraph expectedGraph, String expectedString, StructuredGraph actualGraph, String actualString) { if (!expectedString.equals(actualString)) { String[] expectedLines = expectedString.split("\n"); String[] actualLines = actualString.split("\n"); @@ -883,7 +911,7 @@ } } - static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) { + private static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) { SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST); schedule.apply(graph); StructuredGraph.ScheduleResult scheduleResult = graph.getLastSchedule(); @@ -968,8 +996,8 @@ super(replacements, providers); } - HotSpotSnippetReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { - super(options, providers, snippetReflection, bytecodeProvider, target); + HotSpotSnippetReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { + super(providers, snippetReflection, bytecodeProvider, target); } @Override @@ -1009,14 +1037,25 @@ @Override public boolean canDeferPlugin(GeneratedInvocationPlugin plugin) { + // Fold is always deferred but NodeIntrinsics may have to wait if all their arguments + // aren't constant yet. return plugin.getSource().equals(Fold.class) || plugin.getSource().equals(Node.NodeIntrinsic.class); } @Override + protected boolean canInlinePartialIntrinsicExit() { + return false; + } + + @Override protected boolean tryInvocationPlugin(CallTargetNode.InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) { if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) { return false; } + if (targetMethod.getAnnotation(Fold.class) != null) { + // Always defer Fold until decode time but NodeIntrinsics may fold if they are able. + return false; + } return super.tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType); } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java 2019-04-24 19:25:41.000000000 +0000 @@ -144,10 +144,10 @@ bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); } try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(graalRuntime.getOptions(), p, snippetReflection, bytecodeProvider); + replacements = createReplacements(p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes); + plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, graalRuntime.getOptions()); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { @@ -156,6 +156,7 @@ providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins); + replacements.setProviders(providers); } try (InitTimer rt = timer("instantiate backend")) { return createBackend(config, graalRuntime, providers); @@ -164,8 +165,8 @@ protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, - HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements); + HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements, options); AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false, // /* registerMathPlugins */true); return plugins; @@ -179,8 +180,8 @@ return new HotSpotRegisters(AArch64HotSpotRegisterConfig.threadRegister, AArch64HotSpotRegisterConfig.heapBaseRegister, sp); } - protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { - return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); + protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { + return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); } protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -194,9 +194,19 @@ } public static void emitUncompressCode(AArch64MacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) { + // result = ptr << shift + if (baseReg == null) { + if (shift != 0) { + masm.shl(64, resReg, inputRegister, shift); + } else if (!resReg.equals(inputRegister)) { + masm.movx(resReg, inputRegister); + } + return; + } + // result = base + (ptr << shift) - if (nonNull || baseReg == null) { - masm.add(64, resReg, baseReg == null ? zr : baseReg, inputRegister, AArch64Assembler.ShiftType.LSL, shift); + if (nonNull) { + masm.add(64, resReg, baseReg, inputRegister, AArch64Assembler.ShiftType.LSL, shift); } else { // if ptr is null it has to be null after decompression Label done = new Label(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64.test/src/org/graalvm/compiler/hotspot/aarch64/test/AArch64UncompressPointerTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64.test/src/org/graalvm/compiler/hotspot/aarch64/test/AArch64UncompressPointerTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64.test/src/org/graalvm/compiler/hotspot/aarch64/test/AArch64UncompressPointerTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64.test/src/org/graalvm/compiler/hotspot/aarch64/test/AArch64UncompressPointerTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Arm Limited and 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. + */ + + + +package org.graalvm.compiler.hotspot.aarch64.test; + +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.runtime.JVMCI; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.hotspot.aarch64.AArch64HotSpotMove; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assume.assumeTrue; + +public class AArch64UncompressPointerTest extends GraalCompilerTest { + + private AArch64MacroAssembler masm1; + private AArch64MacroAssembler masm2; + private Register input; + private Register result; + + @Before + public void checkAArch64() { + assumeTrue("skipping AArch64 specific test", JVMCI.getRuntime().getHostJVMCIBackend().getTarget().arch instanceof AArch64); + } + + @Before + public void setupEnvironment() { + TargetDescription target = JVMCI.getRuntime().getHostJVMCIBackend().getTarget(); + masm1 = new AArch64MacroAssembler(target); + masm2 = new AArch64MacroAssembler(target); + input = AArch64.r10; + result = AArch64.r11; + } + + private void emitUncompressPointer(Register base, int shift) { + AArch64HotSpotMove.UncompressPointer.emitUncompressCode(masm2, input, result, base, shift, true); + } + + private void compareAssembly() { + byte[] expected = masm1.close(false); + byte[] actual = masm2.close(false); + assertArrayEquals(expected, actual); + } + + @Test + public void testUncompressPointerWithBase() { + Register base = AArch64.r12; + int shift = 3; + masm1.add(64, result, base, input, AArch64Assembler.ShiftType.LSL, shift); + emitUncompressPointer(base, shift); + compareAssembly(); + } + + @Test + public void testUncompressPointerWithZeroBase() { + int shift = 3; + masm1.shl(64, result, input, shift); + emitUncompressPointer(null, shift); + compareAssembly(); + } + + @Test + public void testUncompressPointerWithZeroBaseAndShift() { + masm1.or(64, result, AArch64.zr, input); + emitUncompressPointer(null, 0); + compareAssembly(); + } + + static class A { + String str; + + A(String str) { + this.str = str; + } + } + + public static String getObjectField(A a) { + return a.str; + } + + @Test + public void testGetObjectField() { + test("getObjectField", new A("asfghjkjhgfd")); + } + + static String[] strings = {"asf", "egfda", "fsdasere", "eqwred", "fgdadgtre", "qwrrtreety"}; + + public static String getArrayMember(int index) { + return strings[index]; + } + + @Test + public void testGetArrayMember() { + test("getArrayMember", 4); + } +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java 2019-04-24 19:25:41.000000000 +0000 @@ -138,10 +138,10 @@ bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); } try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(options, p, snippetReflection, bytecodeProvider); + replacements = createReplacements(p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes); + plugins = createGraphBuilderPlugins(compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, options); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { @@ -159,8 +159,8 @@ protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, - HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements); + HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements, options); AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JAVA_SPECIFICATION_VERSION >= 9); return plugins; } @@ -173,8 +173,8 @@ return new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp); } - protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { - return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); + protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { + return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); } protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java 2019-04-24 19:25:41.000000000 +0000 @@ -36,7 +36,7 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO; import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C; import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW; @@ -89,15 +89,15 @@ RegisterValue exception = rax.asValue(LIRKind.reference(word)); RegisterValue exceptionPc = rdx.asValue(LIRKind.value(word)); CallingConvention exceptionCc = new CallingConvention(0, ILLEGAL, exception, exceptionPc); - register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any())); - register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any())); + register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any())); + register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any())); if (config.useCRC32Intrinsics) { // This stub does callee saving - registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); + registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); } if (config.useCRC32CIntrinsics) { - registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); + registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); } link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_TWO_CONSECUTIVE_BYTES, options, providers, diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -234,7 +234,7 @@ public void test() { HotSpotProviders providers = (HotSpotProviders) getProviders(); HotSpotForeignCallsProviderImpl foreignCalls = (HotSpotForeignCallsProviderImpl) providers.getForeignCalls(); - HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallLinkage.Transition.LEAF_NOFP, HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE); + HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO, HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE); linkage.setCompiledStub(new TestStub(getInitialOptions(), providers, linkage)); runTest("testStub"); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java 2019-04-24 19:25:41.000000000 +0000 @@ -51,6 +51,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.AddressLoweringPhase; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; @@ -103,21 +104,22 @@ Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider); HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes); BytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); - HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(runtime.getOptions(), p, snippetReflection, bytecodeProvider, target); - Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, snippetReflection, replacements, wordTypes); + HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, target); + Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, snippetReflection, replacements, wordTypes, runtime.getOptions()); replacements.setGraphBuilderPlugins(plugins); HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, replacements); HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins); + replacements.setProviders(providers); return createBackend(config, runtime, providers); } protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotMetaAccessProvider metaAccess, HotSpotConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, - HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements); + HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements, options); SPARCGraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false); return plugins; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java 2019-04-24 19:25:41.000000000 +0000 @@ -35,7 +35,7 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO; import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C; import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.internal.vm.compiler.word.LocationIdentity.any; @@ -84,16 +84,16 @@ RegisterValue incomingExceptionPc = i1.asValue(LIRKind.value(word)); CallingConvention outgoingExceptionCc = new CallingConvention(0, ILLEGAL, outgoingException, outgoingExceptionPc); CallingConvention incomingExceptionCc = new CallingConvention(0, ILLEGAL, incomingException, incomingExceptionPc); - register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc, incomingExceptionCc, any())); - register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc, + register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc, incomingExceptionCc, any())); + register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc, incomingExceptionCc, any())); if (config.useCRC32Intrinsics) { // This stub does callee saving - registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); + registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); } if (config.useCRC32CIntrinsics) { - registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); + registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); } super.initialize(providers, options); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -162,7 +162,7 @@ } /** - * Tests {@link ArrayCopySnippets#arraycopyCheckcastSnippet}. + * Tests {@link ArrayCopySnippets#arraycopyGenericSnippet} with checkcast. */ @Test public void testArrayStoreException() { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java 2019-04-24 19:25:41.000000000 +0000 @@ -381,8 +381,11 @@ if (isJDK11OrHigher()) { // Relevant for Java flight recorder add(toBeInvestigated, - "java/util/Base64$Encoder.encodeBlock([BII[BIZ)V", "jdk/jfr/internal/JVM.getEventWriter()Ljava/lang/Object;"); + if (!config.useBase64Intrinsics()) { + add(ignore, + "java/util/Base64$Encoder.encodeBlock([BII[BIZ)V"); + } } if (isJDK12OrHigher()) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java 2019-04-24 19:25:41.000000000 +0000 @@ -32,7 +32,9 @@ import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes; import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS; import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier; +import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; +import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; import java.io.IOException; @@ -73,10 +75,11 @@ import java.util.stream.Collectors; import jdk.internal.vm.compiler.collections.EconomicMap; -import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap; +import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecodes; import org.graalvm.compiler.core.CompilerThreadFactory; +import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.core.test.ReflectionOptionDescriptors; import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.debug.GraalError; @@ -86,11 +89,15 @@ import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; +import org.graalvm.compiler.hotspot.test.CompileTheWorld.LibGraalParams.StackTraceBuffer; import org.graalvm.compiler.options.OptionDescriptors; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; +import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; +import jdk.internal.vm.compiler.libgraal.LibGraal; +import jdk.internal.vm.compiler.libgraal.OptionsEncoder; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; @@ -102,6 +109,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.runtime.JVMCI; import jdk.vm.ci.runtime.JVMCICompiler; +import sun.misc.Unsafe; /** * This class implements compile-the-world functionality with JVMCI. @@ -127,17 +135,19 @@ * Ignored if null. */ public static EconomicMap, Object> parseOptions(String options) { + EconomicMap, Object> values = OptionValues.newOptionMap(); if (options != null) { EconomicMap optionSettings = EconomicMap.create(); for (String optionSetting : options.split("\\s+|#")) { OptionsParser.parseOptionSettingTo(optionSetting, optionSettings); } - EconomicMap, Object> values = OptionValues.newOptionMap(); ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); OptionsParser.parseOptions(optionSettings, values, loader); - return values; } - return EconomicMap.create(); + if (!values.containsKey(HighTier.Options.Inline)) { + values.put(HighTier.Options.Inline, false); + } + return values; } private final HotSpotJVMCIRuntime jvmciRuntime; @@ -165,6 +175,13 @@ */ private final int stopAt; + /** + * Max classes to compile. + * + * @see Options#MaxClasses + */ + private final int maxClasses; + /** Only compile methods matching one of the filters in this array if the array is non-null. */ private final MethodFilter[] methodFilters; @@ -186,8 +203,130 @@ private ThreadPoolExecutor threadPool; - private OptionValues currentOptions; - private final UnmodifiableEconomicMap, Object> compilationOptions; + /** + * Values for {@link CompileTheWorld.Options}. + */ + private final OptionValues harnessOptions; + + /** + * Option values used during compilation. + */ + private final OptionValues compilerOptions; + + /** + * Manages native memory buffers for passing arguments into libgraal and receiving return + * values. The native memory buffers are freed when this object is {@linkplain #close() closed}. + */ + static class LibGraalParams implements AutoCloseable { + + static { + LibGraal.registerNativeMethods(HotSpotJVMCIRuntime.runtime(), CompileTheWorld.class); + } + + /** + * Native memory containing {@linkplain OptionsEncoder encoded} {@link OptionValues}. + */ + static class OptionsBuffer { + private long address; + final int size; + final int hash; + + OptionsBuffer(OptionValues options) { + Map map = new HashMap<>(); + UnmodifiableMapCursor, Object> cursor = options.getMap().getEntries(); + while (cursor.advance()) { + final OptionKey key = cursor.getKey(); + Object value = cursor.getValue(); + map.put(key.getName(), value); + } + + byte[] encoded = OptionsEncoder.encode(map); + size = encoded.length; + hash = Arrays.hashCode(encoded); + address = UNSAFE.allocateMemory(encoded.length); + UNSAFE.copyMemory(encoded, ARRAY_BYTE_BASE_OFFSET, null, address, size); + } + + long getAddress() { + if (address == 0) { + throw new IllegalStateException(); + } + return address; + } + + void free() { + if (address != 0) { + UNSAFE.freeMemory(address); + address = 0; + } + } + } + + /** + * Manages native memory for receiving a {@linkplain Throwable#printStackTrace() stack + * trace} from libgraal serialized via {@link ByteArrayOutputStream} to a byte array. + */ + static class StackTraceBuffer { + final int size; + private long address; + + StackTraceBuffer(int size) { + this.size = size; + address = UNSAFE.allocateMemory(size); + } + + void free() { + if (address != 0L) { + UNSAFE.freeMemory(address); + address = 0L; + } + } + + long getAddress() { + if (address == 0) { + throw new IllegalStateException(); + } + return address; + } + } + + final OptionsBuffer options; + + private final List stackTraceBuffers = new ArrayList<>(); + + /** + * Gets a stack trace buffer for the current thread. + */ + StackTraceBuffer getStackTraceBuffer() { + return stackTraceBuffer.get(); + } + + private final ThreadLocal stackTraceBuffer = new ThreadLocal() { + @Override + protected StackTraceBuffer initialValue() { + StackTraceBuffer buffer = new StackTraceBuffer(10_000); + synchronized (stackTraceBuffers) { + stackTraceBuffers.add(buffer); + } + return buffer; + } + }; + + LibGraalParams(OptionValues options) { + this.options = new OptionsBuffer(options); + } + + @Override + public void close() { + options.free(); + synchronized (stackTraceBuffers) { + for (StackTraceBuffer buffer : stackTraceBuffers) { + buffer.free(); + } + stackTraceBuffers.clear(); + } + } + } /** * Creates a compile-the-world instance. @@ -195,73 +334,99 @@ * @param files {@link File#pathSeparator} separated list of Zip/Jar files to compile * @param startAt index of the class file to start compilation at * @param stopAt index of the class file to stop compilation at + * @param maxClasses maximum number of classes to process * @param methodFilters * @param excludeMethodFilters + * @param harnessOptions values for {@link CompileTheWorld.Options} + * @param compilerOptions option values used by the compiler */ - public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, String files, int startAt, int stopAt, String methodFilters, String excludeMethodFilters, - boolean verbose, OptionValues initialOptions, EconomicMap, Object> compilationOptions) { + public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime, + HotSpotGraalCompiler compiler, + String files, + int startAt, + int stopAt, + int maxClasses, + String methodFilters, + String excludeMethodFilters, + boolean verbose, + OptionValues harnessOptions, + OptionValues compilerOptions) { this.jvmciRuntime = jvmciRuntime; this.compiler = compiler; this.inputClassPath = files; - this.startAt = startAt; - this.stopAt = stopAt; + this.startAt = Math.max(startAt, 1); + this.stopAt = Math.max(stopAt, 1); + this.maxClasses = Math.max(maxClasses, 1); this.methodFilters = methodFilters == null || methodFilters.isEmpty() ? null : MethodFilter.parse(methodFilters); this.excludeMethodFilters = excludeMethodFilters == null || excludeMethodFilters.isEmpty() ? null : MethodFilter.parse(excludeMethodFilters); this.verbose = verbose; - this.currentOptions = initialOptions; + this.harnessOptions = harnessOptions; // Copy the initial options and add in any extra options - EconomicMap, Object> compilationOptionsCopy = EconomicMap.create(initialOptions.getMap()); - compilationOptionsCopy.putAll(compilationOptions); + EconomicMap, Object> compilerOptionsMap = EconomicMap.create(compilerOptions.getMap()); // We want to see stack traces when a method fails to compile - CompilationBailoutAsFailure.putIfAbsent(compilationOptionsCopy, true); - CompilationFailureAction.putIfAbsent(compilationOptionsCopy, Print); + CompilationBailoutAsFailure.putIfAbsent(compilerOptionsMap, true); + CompilationFailureAction.putIfAbsent(compilerOptionsMap, Print); // By default only report statistics for the CTW threads themselves - DebugOptions.MetricsThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld"); - this.compilationOptions = compilationOptionsCopy; + DebugOptions.MetricsThreadFilter.putIfAbsent(compilerOptionsMap, "^CompileTheWorld"); + this.compilerOptions = new OptionValues(compilerOptionsMap); } - public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, OptionValues options) { - this(jvmciRuntime, compiler, Options.Classpath.getValue(options), - Options.StartAt.getValue(options), - Options.StopAt.getValue(options), - Options.MethodFilter.getValue(options), - Options.ExcludeMethodFilter.getValue(options), - Options.Verbose.getValue(options), - options, - parseOptions(Options.Config.getValue(options))); + public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime, + HotSpotGraalCompiler compiler, + OptionValues harnessOptions, + OptionValues compilerOptions) { + this(jvmciRuntime, compiler, Options.Classpath.getValue(harnessOptions), + Options.StartAt.getValue(harnessOptions), + Options.StopAt.getValue(harnessOptions), + Options.MaxClasses.getValue(harnessOptions), + Options.MethodFilter.getValue(harnessOptions), + Options.ExcludeMethodFilter.getValue(harnessOptions), + Options.Verbose.getValue(harnessOptions), + harnessOptions, + new OptionValues(compilerOptions, parseOptions(Options.Config.getValue(harnessOptions)))); } /** * Compiles all methods in all classes in {@link #inputClassPath}. If {@link #inputClassPath} * equals {@link #SUN_BOOT_CLASS_PATH} the boot classes are used. */ + @SuppressWarnings("try") public void compile() throws Throwable { - if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) { - String bcpEntry = null; - if (Java8OrEarlier) { - final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator); - for (int i = 0; i < entries.length && bcpEntry == null; i++) { - String entry = entries[i]; - File entryFile = new File(entry); - if (entryFile.getName().endsWith("rt.jar") && entryFile.isFile()) { - bcpEntry = entry; + try (LibGraalParams libgraal = LibGraal.isAvailable() ? new LibGraalParams(compilerOptions) : null) { + if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) { + String bcpEntry = null; + if (Java8OrEarlier) { + final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator); + for (int i = 0; i < entries.length && bcpEntry == null; i++) { + String entry = entries[i]; + File entryFile = new File(entry); + if (entryFile.getName().endsWith("rt.jar") && entryFile.isFile()) { + bcpEntry = entry; + } } + if (bcpEntry == null) { + throw new GraalError("Could not find rt.jar on boot class path %s", System.getProperty(SUN_BOOT_CLASS_PATH)); + } + } else { + bcpEntry = JRT_CLASS_PATH_ENTRY; } - if (bcpEntry == null) { - throw new GraalError("Could not find rt.jar on boot class path %s", System.getProperty(SUN_BOOT_CLASS_PATH)); - } + compile(bcpEntry, libgraal); } else { - bcpEntry = JRT_CLASS_PATH_ENTRY; + compile(inputClassPath, libgraal); } - compile(bcpEntry); - } else { - compile(inputClassPath); } } + private AutoCloseable enterCompilation() { + if (!LibGraal.isAvailable()) { + return null; + } + return new LibGraalParams(compilerOptions); + } + public void println() { println(""); } @@ -486,6 +651,19 @@ return true; } + private ClassPathEntry openClassPathEntry(String entry) throws IOException { + if (entry.endsWith(".zip") || entry.endsWith(".jar")) { + return new JarClassPathEntry(entry); + } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) { + return new JRTClassPathEntry(entry, Options.LimitModules.getValue(harnessOptions)); + } else { + if (!new File(entry).isDirectory()) { + return null; + } + return new DirClassPathEntry(entry); + } + } + /** * Compiles all methods in all classes in a given class path. * @@ -493,23 +671,25 @@ * @throws IOException */ @SuppressWarnings("try") - private void compile(String classPath) throws IOException { + private void compile(String classPath, LibGraalParams libgraal) throws IOException { final String[] entries = classPath.split(File.pathSeparator); long start = System.currentTimeMillis(); Map initialThreads = Thread.getAllStackTraces(); - try { - // compile dummy method to get compiler initialized outside of the - // config debug override. - HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod( - CompileTheWorld.class.getDeclaredMethod("dummy")); - int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; - boolean useProfilingInfo = false; - boolean installAsDefault = false; - CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault, currentOptions); - task.runCompilation(); - } catch (NoSuchMethodException | SecurityException e1) { - printStackTrace(e1); + if (libgraal == null) { + try { + // compile dummy method to get compiler initialized outside of the + // config debug override. + HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod( + CompileTheWorld.class.getDeclaredMethod("dummy")); + int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; + boolean useProfilingInfo = false; + boolean installAsDefault = false; + CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault); + task.runCompilation(compilerOptions); + } catch (NoSuchMethodException | SecurityException e1) { + printStackTrace(e1); + } } /* @@ -517,8 +697,8 @@ * DebugValueThreadFilter to filter on the thread names. */ int threadCount = 1; - if (Options.MultiThreaded.getValue(currentOptions)) { - threadCount = Options.Threads.getValue(currentOptions); + if (Options.MultiThreaded.getValue(harnessOptions)) { + threadCount = Options.Threads.getValue(harnessOptions); if (threadCount == 0) { threadCount = Runtime.getRuntime().availableProcessors(); } @@ -526,26 +706,37 @@ running = true; } - OptionValues savedOptions = currentOptions; - currentOptions = new OptionValues(compilationOptions); threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new CompilerThreadFactory("CompileTheWorld")); - try { - for (int i = 0; i < entries.length; i++) { - final String entry = entries[i]; - - ClassPathEntry cpe; - if (entry.endsWith(".zip") || entry.endsWith(".jar")) { - cpe = new JarClassPathEntry(entry); - } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) { - cpe = new JRTClassPathEntry(entry, Options.LimitModules.getValue(currentOptions)); - } else { - if (!new File(entry).isDirectory()) { - println("CompileTheWorld : Skipped classes in " + entry); - println(); - continue; + int compileStartAt = startAt; + int compileStopAt = stopAt; + int compileStep = 1; + if (maxClasses != Integer.MAX_VALUE) { + int totalClassFileCount = 0; + for (String entry : entries) { + try (ClassPathEntry cpe = openClassPathEntry(entry)) { + if (cpe != null) { + totalClassFileCount += cpe.getClassNames().size(); } - cpe = new DirClassPathEntry(entry); + } + } + + int lastClassFile = totalClassFileCount - 1; + compileStartAt = Math.min(startAt, lastClassFile); + compileStopAt = Math.min(stopAt, lastClassFile); + int range = compileStopAt - compileStartAt + 1; + if (maxClasses < range) { + compileStep = range / maxClasses; + } + } + + for (int i = 0; i < entries.length; i++) { + final String entry = entries[i]; + try (ClassPathEntry cpe = openClassPathEntry(entry)) { + if (cpe == null) { + println("CompileTheWorld : Skipped classes in " + entry); + println(); + continue; } if (methodFilters == null || methodFilters.length == 0) { @@ -565,12 +756,16 @@ for (String className : cpe.getClassNames()) { // Are we done? - if (classFileCounter >= stopAt) { + if (classFileCounter >= compileStopAt) { break; } classFileCounter++; + if (compileStep > 1 && ((classFileCounter - compileStartAt) % compileStep) != 0) { + continue; + } + if (className.startsWith("jdk.management.") || className.startsWith("jdk.internal.cmm.*") || // GR-5881: The class initializer for @@ -606,28 +801,29 @@ } // Are we compiling this class? - if (classFileCounter >= startAt) { - println("CompileTheWorld (%d) : %s", classFileCounter, className); + if (classFileCounter >= compileStartAt) { + long start0 = System.currentTimeMillis(); // Compile each constructor/method in the class. for (Constructor constructor : javaClass.getDeclaredConstructors()) { HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(constructor); if (canBeCompiled(javaMethod, constructor.getModifiers())) { - compileMethod(javaMethod); + compileMethod(javaMethod, libgraal); } } for (Method method : javaClass.getDeclaredMethods()) { HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method); if (canBeCompiled(javaMethod, method.getModifiers())) { - compileMethod(javaMethod); + compileMethod(javaMethod, libgraal); } } // Also compile the class initializer if it exists HotSpotResolvedJavaMethod clinit = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaType(javaClass).getClassInitializer(); if (clinit != null && canBeCompiled(clinit, clinit.getModifiers())) { - compileMethod(clinit); + compileMethod(clinit, libgraal); } + println("CompileTheWorld (%d) : %s (%d ms)", classFileCounter, className, System.currentTimeMillis() - start0); } } catch (Throwable t) { if (isClassIncluded(className)) { @@ -636,10 +832,7 @@ } } } - cpe.close(); } - } finally { - currentOptions = savedOptions; } if (!running) { @@ -661,11 +854,12 @@ long elapsedTime = System.currentTimeMillis() - start; println(); - if (Options.MultiThreaded.getValue(currentOptions)) { - TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), elapsedTime, + int compiledClasses = classFileCounter > compileStartAt ? classFileCounter - compileStartAt : 0; + if (Options.MultiThreaded.getValue(harnessOptions)) { + TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), elapsedTime, compileTime.get(), memoryUsed.get()); } else { - TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get()); + TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get()); } // Apart from the main thread, there should be only be daemon threads @@ -712,7 +906,7 @@ } @SuppressWarnings("try") - private void compileMethod(HotSpotResolvedJavaMethod method) throws InterruptedException, ExecutionException { + private void compileMethod(HotSpotResolvedJavaMethod method, LibGraalParams libgraal) throws InterruptedException, ExecutionException { if (methodFilters != null && !MethodFilter.matches(methodFilters, method)) { return; } @@ -723,13 +917,7 @@ @Override public void run() { waitToRun(); - OptionValues savedOptions = currentOptions; - currentOptions = new OptionValues(compilationOptions); - try { - compileMethod(method, classFileCounter); - } finally { - currentOptions = savedOptions; - } + compileMethod(method, classFileCounter, libgraal); } }); if (threadPool.getCorePoolSize() == 1) { @@ -737,23 +925,66 @@ } } + private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe(); + + static native long compileMethodInLibgraal(long isolateThread, + long methodHandle, + boolean useProfilingInfo, + boolean installAsDefault, + long optionsAddress, + int optionsSize, + int optionsHash, + long encodedThrowableBufferAddress, + int encodedThrowableBufferSize); + /** * Compiles a method and gathers some statistics. */ - private void compileMethod(HotSpotResolvedJavaMethod method, int counter) { + private void compileMethod(HotSpotResolvedJavaMethod method, int counter, LibGraalParams libgraal) { try { long start = System.currentTimeMillis(); long allocatedAtStart = getCurrentThreadAllocatedBytes(); - int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; - HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L); // For more stable CTW execution, disable use of profiling information boolean useProfilingInfo = false; boolean installAsDefault = false; - CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault, currentOptions); - task.runCompilation(); + HotSpotInstalledCode installedCode; + if (libgraal != null) { + HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); + long methodHandle = LibGraal.translate(runtime, method); + long isolateThread = LibGraal.getIsolateThread(); + + StackTraceBuffer stackTraceBuffer = libgraal.getStackTraceBuffer(); + + long stackTraceBufferAddress = stackTraceBuffer.getAddress(); + long installedCodeHandle = compileMethodInLibgraal(isolateThread, + methodHandle, + useProfilingInfo, + installAsDefault, + libgraal.options.getAddress(), + libgraal.options.size, + libgraal.options.hash, + stackTraceBufferAddress, + stackTraceBuffer.size); + + installedCode = LibGraal.unhand(runtime, HotSpotInstalledCode.class, installedCodeHandle); + if (installedCode == null) { + int length = UNSAFE.getInt(stackTraceBufferAddress); + byte[] data = new byte[length]; + UNSAFE.copyMemory(null, stackTraceBufferAddress + Integer.BYTES, data, ARRAY_BYTE_BASE_OFFSET, length); + String stackTrace = new String(data).trim(); + println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r")); + println(stackTrace); + } + + } else { + int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; + HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L); + CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault); + task.runCompilation(compilerOptions); + installedCode = task.getInstalledCode(); + } // Invalidate the generated code so the code cache doesn't fill up - HotSpotInstalledCode installedCode = task.getInstalledCode(); if (installedCode != null) { installedCode.invalidate(); } @@ -799,13 +1030,12 @@ } static class Options { - // @formatter:off public static final OptionKey Help = new OptionKey<>(false); public static final OptionKey Classpath = new OptionKey<>(CompileTheWorld.SUN_BOOT_CLASS_PATH); public static final OptionKey Verbose = new OptionKey<>(true); /** - * Ignore Graal classes by default to avoid problems associated with compiling - * snippets and method substitutions. + * Ignore Graal classes by default to avoid problems associated with compiling snippets and + * method substitutions. */ public static final OptionKey LimitModules = new OptionKey<>("~jdk.internal.vm.compiler"); public static final OptionKey Iterations = new OptionKey<>(1); @@ -813,10 +1043,12 @@ public static final OptionKey ExcludeMethodFilter = new OptionKey<>(null); public static final OptionKey StartAt = new OptionKey<>(1); public static final OptionKey StopAt = new OptionKey<>(Integer.MAX_VALUE); + public static final OptionKey MaxClasses = new OptionKey<>(Integer.MAX_VALUE); public static final OptionKey Config = new OptionKey<>(null); public static final OptionKey MultiThreaded = new OptionKey<>(false); public static final OptionKey Threads = new OptionKey<>(0); + // @formatter:off static final ReflectionOptionDescriptors DESCRIPTORS = new ReflectionOptionDescriptors(Options.class, "Help", "List options and their help messages and then exit.", "Classpath", "Class path denoting methods to compile. Default is to compile boot classes.", @@ -826,21 +1058,24 @@ "Iterations", "The number of iterations to perform.", "MethodFilter", "Only compile methods matching this filter.", "ExcludeMethodFilter", "Exclude methods matching this filter from compilation.", - "StartAt", "First class to consider for compilation.", - "StopAt", "Last class to consider for compilation.", - "Config", "Option value overrides to use during compile the world. For example, " + - "to disable inlining and partial escape analysis specify 'PartialEscapeAnalysis=false Inline=false'. " + - "The format for each option is the same as on the command line just without the '-Dgraal.' prefix.", + "StartAt", "First class to consider for compilation (default = 1).", + "StopAt", "Last class to consider for compilation (default = ).", + "MaxClasses", "Maximum number of classes to process (default = ). " + + "Ignored if less than (StopAt - StartAt + 1).", + "Config", "Option values to use during compile the world compilations. For example, " + + "to disable partial escape analysis and print compilations specify " + + "'PartialEscapeAnalysis=false PrintCompilation=true'. " + + "Unless explicitly enabled with 'Inline=true' here, inlining is disabled.", "MultiThreaded", "Run using multiple threads for compilation.", "Threads", "Number of threads to use for multithreaded execution. Defaults to Runtime.getRuntime().availableProcessors()."); // @formatter:on } - public static OptionValues loadOptions(OptionValues initialValues) { + public static OptionValues loadHarnessOptions() { EconomicMap, Object> values = OptionValues.newOptionMap(); List loader = singletonList(DESCRIPTORS); OptionsParser.parseOptions(extractEntries(System.getProperties(), "CompileTheWorld.", true), values, loader); - OptionValues options = new OptionValues(initialValues, values); + OptionValues options = new OptionValues(values); if (Options.Help.getValue(options)) { options.printHelp(loader, System.out, "CompileTheWorld."); System.exit(0); @@ -853,14 +1088,14 @@ HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) jvmciRuntime.getCompiler(); HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); HotSpotCodeCacheProvider codeCache = graalRuntime.getHostProviders().getCodeCache(); - OptionValues options = loadOptions(graalRuntime.getOptions()); + OptionValues harnessOptions = loadHarnessOptions(); - int iterations = Options.Iterations.getValue(options); + int iterations = Options.Iterations.getValue(harnessOptions); for (int i = 0; i < iterations; i++) { codeCache.resetCompilationStatistics(); TTY.println("CompileTheWorld : iteration " + i); - CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, options); + CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, harnessOptions, graalRuntime.getOptions()); ctw.compile(); } // This is required as non-daemon threads can be started by class initializers diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -27,11 +27,10 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure; import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction; -import jdk.internal.vm.compiler.collections.EconomicMap; import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction; +import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; -import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import org.junit.Test; @@ -50,8 +49,25 @@ HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); System.setProperty("CompileTheWorld.LimitModules", "java.base"); OptionValues initialOptions = getInitialOptions(); - EconomicMap, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false"); - new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile(); + OptionValues harnessOptions = new OptionValues(OptionValues.newOptionMap()); + int startAt = 1; + int stopAt = 5; + int maxClasses = Integer.MAX_VALUE; + String methodFilters = null; + String excludeMethodFilters = null; + boolean verbose = false; + CompileTheWorld ctw = new CompileTheWorld(runtime, + (HotSpotGraalCompiler) runtime.getCompiler(), + CompileTheWorld.SUN_BOOT_CLASS_PATH, + startAt, + stopAt, + maxClasses, + methodFilters, + excludeMethodFilters, + verbose, + harnessOptions, + new OptionValues(initialOptions, HighTier.Options.Inline, false)); + ctw.compile(); assert CompilationBailoutAsFailure.getValue(initialOptions) == originalBailoutAction; assert CompilationFailureAction.getValue(initialOptions) == originalFailureAction; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java 2019-04-24 19:25:41.000000000 +0000 @@ -79,7 +79,7 @@ long jvmciEnv = 0L; HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) method, bci, jvmciEnv); HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); - CompilationTask task = new CompilationTask(runtime, compiler, request, true, true, debug.getOptions()); + CompilationTask task = new CompilationTask(runtime, compiler, request, true, true); if (method instanceof HotSpotResolvedJavaMethod) { HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotBase64Test.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotBase64Test.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotBase64Test.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotBase64Test.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.hotspot.test; + +import static org.junit.Assume.assumeTrue; + +import java.util.Base64; + +import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; +import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Before; +import org.junit.Test; + +public class HotSpotBase64Test extends HotSpotGraalCompilerTest { + + // Checkstyle: stop + private static final String lipsum = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata "; + // Checkstyle: resume + + @Before + public void sanity() { + HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class); + assumeTrue("Enable test case when the hotspot intrinsic is available", rt.getVMConfig().useBase64Intrinsics()); + } + + @Test + public void testEncode() { + test(getResolvedJavaMethod(Base64.Encoder.class, "encode", byte[].class), Base64.getEncoder(), lipsum.getBytes()); + } + +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java 2019-04-24 19:25:41.000000000 +0000 @@ -137,8 +137,8 @@ HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, jvmciEnv); - CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions()); - task.runCompilation(); + CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false); + task.runCompilation(getInitialOptions()); } } @@ -156,8 +156,8 @@ HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, JVMCICompiler.INVOCATION_ENTRY_BCI, jvmciEnv); HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); OptionValues options = getInitialOptions(); - CompilationTask task = new CompilationTask(runtime, compiler, request, true, false, options); - task.runCompilation(); + CompilationTask task = new CompilationTask(runtime, compiler, request, true, false); + task.runCompilation(options); } } } @@ -180,10 +180,10 @@ public void run() { compileAndTime("simple"); compileAndTime("complex"); - OptionValues options = CompileTheWorld.loadOptions(getInitialOptions()); - if (CompileTheWorld.Options.Classpath.getValue(options) != CompileTheWorld.SUN_BOOT_CLASS_PATH) { + OptionValues harnessOptions = CompileTheWorld.loadHarnessOptions(); + if (CompileTheWorld.Options.Classpath.getValue(harnessOptions) != CompileTheWorld.SUN_BOOT_CLASS_PATH) { HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); - CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), options); + CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), harnessOptions, getInitialOptions()); try { ctw.compile(); } catch (Throwable e) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectHashCodeInliningTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectHashCodeInliningTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectHashCodeInliningTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectHashCodeInliningTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.hotspot.test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.nodes.memory.ReadNode; +import org.junit.Assume; +import org.junit.Test; + +public class ObjectHashCodeInliningTest extends GraalCompilerTest { + + public static int getHash(Object obj) { + return obj.hashCode(); + } + + @Test + public void testInstallCodeInvalidation() { + for (int i = 0; i < 100000; i++) { + getHash(i % 1000 == 0 ? new Object() : ""); + } + + ResolvedJavaMethod method = getResolvedJavaMethod("getHash"); + StructuredGraph graph = parseForCompile(method); + for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.TYPE)) { + if ("Object.hashCode".equals(callTargetNode.targetName())) { + Assume.assumeTrue(callTargetNode.getProfile() != null); + } + } + compile(method, graph); + } + + private static boolean containsForeignCallToIdentityHashCode(StructuredGraph graph) { + for (ForeignCallNode foreignCallNode : graph.getNodes().filter(ForeignCallNode.class)) { + if ("identity_hashcode".equals(foreignCallNode.getDescriptor().getName())) { + return true; + } + } + return false; + } + + private static boolean containsReadStringHash(StructuredGraph graph) { + for (ReadNode readNode : graph.getNodes().filter(ReadNode.class)) { + if ("String.hash".equals(readNode.getLocationIdentity().toString())) { + return true; + } + } + return false; + } + + @Override + protected boolean checkHighTierGraph(StructuredGraph graph) { + return containsForeignCallToIdentityHashCode(graph) && containsReadStringHash(graph); + } + +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java 2019-04-24 19:25:41.000000000 +0000 @@ -900,8 +900,7 @@ assert next == newBlocks.length - 1; // Add unwind block. - int deoptBci = code.getMethod().isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI; - ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock(deoptBci); + ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock(BytecodeFrame.AFTER_EXCEPTION_BCI); unwindBlock.setId(newBlocks.length - 1); newBlocks[newBlocks.length - 1] = unwindBlock; diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java 2019-04-24 19:25:41.000000000 +0000 @@ -27,6 +27,7 @@ import static java.lang.String.format; import static java.lang.reflect.Modifier.STATIC; import static java.lang.reflect.Modifier.SYNCHRONIZED; +import static jdk.vm.ci.code.BytecodeFrame.UNKNOWN_BCI; import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; import static jdk.vm.ci.meta.DeoptimizationAction.None; @@ -256,7 +257,7 @@ import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins; import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_FAST_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING; @@ -271,6 +272,7 @@ import jdk.internal.vm.compiler.collections.EconomicMap; import jdk.internal.vm.compiler.collections.Equivalence; +import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecode; @@ -383,6 +385,7 @@ import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; +import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode; @@ -488,10 +491,11 @@ protected static final CounterKey EXPLICIT_EXCEPTIONS = DebugContext.counter("ExplicitExceptions"); /** - * A scoped object for tasks to be performed after parsing an intrinsic such as processing + * A scoped object for tasks to be performed after inlining during parsing such as processing * {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frames states. */ - static class IntrinsicScope implements AutoCloseable { + static class InliningScope implements AutoCloseable { + final ResolvedJavaMethod callee; FrameState stateBefore; final Mark mark; final BytecodeParser parser; @@ -502,44 +506,41 @@ * * @param parser the parsing context of the intrinsic */ - IntrinsicScope(BytecodeParser parser) { + InliningScope(BytecodeParser parser) { this.parser = parser; assert parser.parent == null; assert parser.bci() == 0; mark = null; + callee = null; } /** - * Creates a scope for parsing an intrinsic during graph builder inlining. + * Creates a scope for graph builder inlining. * * @param parser the parsing context of the (non-intrinsic) method calling the intrinsic * @param args the arguments to the call */ - IntrinsicScope(BytecodeParser parser, JavaKind[] argSlotKinds, ValueNode[] args) { + InliningScope(BytecodeParser parser, ResolvedJavaMethod callee, ValueNode[] args) { + this.callee = callee; assert !parser.parsingIntrinsic(); this.parser = parser; mark = parser.getGraph().getMark(); + JavaKind[] argSlotKinds = callee.getSignature().toParameterKinds(!callee.isStatic()); stateBefore = parser.frameState.create(parser.bci(), parser.getNonIntrinsicAncestor(), false, argSlotKinds, args); } @Override public void close() { - IntrinsicContext intrinsic = parser.intrinsicContext; - if (intrinsic != null && intrinsic.isPostParseInlined()) { - return; - } - - processPlaceholderFrameStates(intrinsic); + processPlaceholderFrameStates(false); } /** * Fixes up the {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frame states * added to the graph while parsing/inlining the intrinsic for which this object exists. */ - private void processPlaceholderFrameStates(IntrinsicContext intrinsic) { + protected void processPlaceholderFrameStates(boolean isCompilationRoot) { StructuredGraph graph = parser.getGraph(); graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "Before processPlaceholderFrameStates in %s", parser.method); - boolean sawInvalidFrameState = false; for (Node node : graph.getNewNodes(mark)) { if (node instanceof FrameState) { FrameState frameState = (FrameState) node; @@ -547,7 +548,7 @@ if (frameState.bci == BytecodeFrame.AFTER_BCI) { if (parser.getInvokeReturnType() == null) { // A frame state in a root compiled intrinsic. - assert intrinsic.isCompilationRoot(); + assert isCompilationRoot; FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); frameState.replaceAndDelete(newFrameState); } else { @@ -557,7 +558,7 @@ if (frameState.stackSize() != 0) { ValueNode returnVal = frameState.stackAt(0); if (!ReturnToCallerData.containsReturnValue(returnDataList, returnVal)) { - throw new GraalError("AFTER_BCI frame state within an intrinsic has a non-return value on the stack: %s", returnVal); + throw new GraalError("AFTER_BCI frame state within a sub-parse has a non-return value on the stack: %s", returnVal); } // Swap the top-of-stack value with the return value @@ -569,15 +570,7 @@ newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); frameStateBuilder.push(returnKind, tos); } else if (returnKind != JavaKind.Void) { - // If the intrinsic returns a non-void value, then any frame - // state with an empty stack is invalid as it cannot - // be used to deoptimize to just after the call returns. - // These invalid frame states are expected to be removed - // by later compilation stages. - FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); - newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); - frameState.replaceAndDelete(newFrameState); - sawInvalidFrameState = true; + handleReturnMismatch(graph, frameState); } else { // An intrinsic for a void method. FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), null); @@ -592,7 +585,7 @@ if (stateBefore != frameState) { frameState.replaceAndDelete(stateBefore); } - } else if (frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { + } else if (frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI || (frameState.bci == BytecodeFrame.UNWIND_BCI && !callee.isSynchronized())) { // This is a frame state for the entry point to an exception // dispatcher in an intrinsic. For example, the invoke denoting // a partial intrinsic exit will have an edge to such a @@ -603,41 +596,102 @@ // namely the exception object. assert frameState.rethrowException(); ValueNode exceptionValue = frameState.stackAt(0); - ExceptionObjectNode exceptionObject = (ExceptionObjectNode) GraphUtil.unproxify(exceptionValue); FrameStateBuilder dispatchState = parser.frameState.copy(); dispatchState.clearStack(); dispatchState.push(JavaKind.Object, exceptionValue); dispatchState.setRethrowException(true); - FrameState newFrameState = dispatchState.create(parser.bci(), exceptionObject); - frameState.replaceAndDelete(newFrameState); - newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); + for (Node usage : frameState.usages()) { + FrameState newFrameState = dispatchState.create(parser.bci(), (StateSplit) usage); + frameState.replaceAndDelete(newFrameState); + newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); + } + } else if (frameState.bci == BytecodeFrame.UNWIND_BCI) { + if (graph.getGuardsStage().allowsFloatingGuards()) { + throw GraalError.shouldNotReachHere("Cannot handle this UNWIND_BCI"); + } + // hope that by construction, there are no fixed guard after this unwind + // and before an other state split } else { - assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI; + assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI : frameState.bci; } } } } + graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After processPlaceholderFrameStates in %s", parser.method); + } + + @SuppressWarnings("unused") + protected void handleReturnMismatch(StructuredGraph g, FrameState fs) { + throw GraalError.shouldNotReachHere("Unexpected return kind mismatch in " + parser.method + " at FS " + fs); + } + } + + static class IntrinsicScope extends InliningScope { + boolean sawInvalidFrameState; + + IntrinsicScope(BytecodeParser parser) { + super(parser); + } + + IntrinsicScope(BytecodeParser parser, ResolvedJavaMethod callee, ValueNode[] args) { + super(parser, callee, args); + } + + @Override + public void close() { + IntrinsicContext intrinsic = parser.intrinsicContext; + boolean isRootCompilation; + if (intrinsic != null) { + if (intrinsic.isPostParseInlined()) { + return; + } + isRootCompilation = intrinsic.isCompilationRoot(); + } else { + isRootCompilation = false; + } + processPlaceholderFrameStates(isRootCompilation); if (sawInvalidFrameState) { JavaKind returnKind = parser.getInvokeReturnType().getJavaKind(); FrameStateBuilder frameStateBuilder = parser.frameState; ValueNode returnValue = frameStateBuilder.pop(returnKind); + StructuredGraph graph = parser.lastInstr.graph(); StateSplitProxyNode proxy = graph.add(new StateSplitProxyNode(returnValue)); parser.lastInstr.setNext(proxy); frameStateBuilder.push(returnKind, proxy); proxy.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), proxy)); parser.lastInstr = proxy; } - graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After processPlaceholderFrameStates in %s", parser.method); + } + + @Override + protected void handleReturnMismatch(StructuredGraph g, FrameState fs) { + // If the intrinsic returns a non-void value, then any frame + // state with an empty stack is invalid as it cannot + // be used to deoptimize to just after the call returns. + // These invalid frame states are expected to be removed + // by later compilation stages. + FrameState newFrameState = g.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); + newFrameState.setNodeSourcePosition(fs.getNodeSourcePosition()); + fs.replaceAndDelete(newFrameState); + sawInvalidFrameState = true; } } private static class Target { - FixedNode fixed; - FrameStateBuilder state; + final FixedNode entry; + final FixedNode originalEntry; + final FrameStateBuilder state; + + Target(FixedNode entry, FrameStateBuilder state) { + this.entry = entry; + this.state = state; + this.originalEntry = null; + } - Target(FixedNode fixed, FrameStateBuilder state) { - this.fixed = fixed; + Target(FixedNode entry, FrameStateBuilder state, FixedNode originalEntry) { + this.entry = entry; this.state = state; + this.originalEntry = originalEntry; } } @@ -1748,7 +1802,7 @@ // edge. Finally, we know that this intrinsic is parsed for late inlining, // so the bci must be set to unknown, so that the inliner patches it later. assert intrinsicContext.isPostParseInlined(); - invokeBci = BytecodeFrame.UNKNOWN_BCI; + invokeBci = UNKNOWN_BCI; profile = null; edgeAction = graph.method().getAnnotation(Snippet.class) == null ? ExceptionEdgeAction.INCLUDE_AND_HANDLE : ExceptionEdgeAction.OMIT; } @@ -2064,7 +2118,14 @@ AbstractBeginNode intrinsicBranch = graph.add(new BeginNode()); AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode()); - append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY)); + // In the adjustment above, we filter out receiver types that select the intrinsic as + // virtual call target. This means the recorded types in the adjusted profile will + // definitely not call into the intrinsic. Note that the following branch probability is + // still not precise -- the previously-not-recorded receiver types in the original + // profile might or might not call into the intrinsic. Yet we accumulate them into the + // probability of the intrinsic branch, assuming that the not-recorded types will only + // be a small fraction. + append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, profile != null ? profile.getNotRecordedProbability() : LIKELY_PROBABILITY)); lastInstr = intrinsicBranch; return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile); } else { @@ -2223,7 +2284,7 @@ for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { InlineInfo inlineInfo = plugin.shouldInlineInvoke(this, targetMethod, args); if (inlineInfo != null) { - if (inlineInfo.getMethodToInline() != null) { + if (inlineInfo.allowsInlining()) { if (inline(targetMethod, inlineInfo.getMethodToInline(), inlineInfo.getIntrinsicBytecodeProvider(), args)) { return SUCCESSFULLY_INLINED; } @@ -2277,6 +2338,134 @@ return false; } + /** + * Inline a method substitution graph. This is necessary for libgraal as substitutions only + * exist as encoded graphs and can't be parsed directly into the caller. + */ + @Override + @SuppressWarnings("try") + public boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, InvocationPlugin.Receiver receiver, ValueNode[] args) { + if (receiver != null) { + receiver.get(); + } + + InvokeWithExceptionNode withException = null; + FixedWithNextNode replacee = lastInstr; + try (DebugContext.Scope a = debug.scope("instantiate", substituteGraph)) { + // Inline the snippet nodes, replacing parameters with the given args in the process + StartNode entryPointNode = substituteGraph.start(); + FixedNode firstCFGNode = entryPointNode.next(); + StructuredGraph replaceeGraph = replacee.graph(); + Mark mark = replaceeGraph.getMark(); + try (InliningScope inlineScope = new IntrinsicScope(this, targetMethod, args)) { + + EconomicMap replacementsMap = EconomicMap.create(Equivalence.IDENTITY); + for (ParameterNode param : substituteGraph.getNodes().filter(ParameterNode.class)) { + replacementsMap.put(param, args[param.index()]); + } + replacementsMap.put(entryPointNode, AbstractBeginNode.prevBegin(replacee)); + + debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "Before inlining method substitution %s", substituteGraph.method()); + UnmodifiableEconomicMap duplicates = inlineMethodSubstitution(replaceeGraph, substituteGraph, replacementsMap); + + FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); + replacee.setNext(firstCFGNodeDuplicate); + debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After inlining method substitution %s", substituteGraph.method()); + + // Handle partial intrinsic exits + for (Node node : graph.getNewNodes(mark)) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + if (invoke.bci() == BytecodeFrame.UNKNOWN_BCI) { + invoke.replaceBci(bci()); + } + if (node instanceof InvokeWithExceptionNode) { + // The graphs for MethodSubsitutions are produced assuming that + // exceptions + // must be dispatched. If the calling context doesn't want exception + // then + // convert back into a normal InvokeNode. + assert withException == null : "only one invoke expected"; + withException = (InvokeWithExceptionNode) node; + BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor(); + if (intrinsicCallSiteParser != null && intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null) == ExceptionEdgeAction.OMIT) { + InvokeNode newInvoke = graph.add(new InvokeNode(withException)); + newInvoke.setStateDuring(withException.stateDuring()); + newInvoke.setStateAfter(withException.stateAfter()); + withException.killExceptionEdge(); + AbstractBeginNode next = withException.killKillingBegin(); + FixedWithNextNode pred = (FixedWithNextNode) withException.predecessor(); + pred.setNext(newInvoke); + withException.setNext(null); + newInvoke.setNext(next); + withException.replaceAndDelete(newInvoke); + } else { + // Disconnnect exception edge + withException.killExceptionEdge(); + } + } + } else if (node instanceof ForeignCallNode) { + ForeignCallNode call = (ForeignCallNode) node; + if (call.getBci() == BytecodeFrame.UNKNOWN_BCI) { + call.setBci(bci()); + if (call.stateAfter() != null && call.stateAfter().bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) { + call.setStateAfter(inlineScope.stateBefore); + } + } + } + } + + ArrayList calleeReturnDataList = new ArrayList<>(); + for (ReturnNode n : substituteGraph.getNodes().filter(ReturnNode.class)) { + ReturnNode returnNode = (ReturnNode) duplicates.get(n); + FixedWithNextNode predecessor = (FixedWithNextNode) returnNode.predecessor(); + calleeReturnDataList.add(new ReturnToCallerData(returnNode.result(), predecessor)); + predecessor.setNext(null); + returnNode.safeDelete(); + } + + // Merge multiple returns + processCalleeReturn(targetMethod, inlineScope, calleeReturnDataList); + + // Exiting this scope causes processing of the placeholder frame states. + } + + if (withException != null && withException.isAlive()) { + // Connect exception edge into main graph + AbstractBeginNode exceptionEdge = handleException(null, bci(), false); + withException.setExceptionEdge(exceptionEdge); + } + + debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this); + return true; + } catch (Throwable t) { + throw debug.handle(t); + } + } + + private static UnmodifiableEconomicMap inlineMethodSubstitution(StructuredGraph replaceeGraph, StructuredGraph snippet, + EconomicMap replacementsMap) { + try (InliningLog.UpdateScope scope = replaceeGraph.getInliningLog().openUpdateScope((oldNode, newNode) -> { + InliningLog log = replaceeGraph.getInliningLog(); + if (oldNode == null) { + log.trackNewCallsite(newNode); + } + })) { + StartNode entryPointNode = snippet.start(); + ArrayList nodes = new ArrayList<>(snippet.getNodeCount()); + for (Node node : snippet.getNodes()) { + if (node != entryPointNode && node != entryPointNode.stateAfter()) { + nodes.add(node); + } + } + UnmodifiableEconomicMap duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacementsMap); + if (scope != null) { + replaceeGraph.getInliningLog().addLog(duplicates, snippet.getInliningLog()); + } + return duplicates; + } + } + @Override public boolean intrinsify(BytecodeProvider intrinsicBytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) { if (receiver != null) { @@ -2441,7 +2630,8 @@ FixedWithNextNode calleeBeforeUnwindNode = null; ValueNode calleeUnwindValue = null; - try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) { + try (InliningScope s = parsingIntrinsic() ? null : (calleeIntrinsicContext != null ? new IntrinsicScope(this, targetMethod, args) + : new InliningScope(this, targetMethod, args))) { BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext); FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph, graphBuilderConfig.retainLocalVariables()); if (!targetMethod.isStatic()) { @@ -2450,35 +2640,9 @@ startFrameState.initializeFromArgumentsArray(args); parser.build(this.lastInstr, startFrameState); - if (parser.returnDataList == null) { - /* Callee does not return. */ - lastInstr = null; - } else { - ValueNode calleeReturnValue; - MergeNode returnMergeNode = null; - if (s != null) { - s.returnDataList = parser.returnDataList; - } - if (parser.returnDataList.size() == 1) { - /* Callee has a single return, we can continue parsing at that point. */ - ReturnToCallerData singleReturnData = parser.returnDataList.get(0); - lastInstr = singleReturnData.beforeReturnNode; - calleeReturnValue = singleReturnData.returnValue; - } else { - assert parser.returnDataList.size() > 1; - /* Callee has multiple returns, we need to insert a control flow merge. */ - returnMergeNode = graph.add(new MergeNode()); - calleeReturnValue = ValueMergeUtil.mergeValueProducers(returnMergeNode, parser.returnDataList, returnData -> returnData.beforeReturnNode, returnData -> returnData.returnValue); - } + List calleeReturnDataList = parser.returnDataList; - if (calleeReturnValue != null) { - frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue); - } - if (returnMergeNode != null) { - returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode)); - lastInstr = finishInstruction(returnMergeNode, frameState); - } - } + processCalleeReturn(targetMethod, s, calleeReturnDataList); /* * Propagate any side effects into the caller when parsing intrinsics. */ @@ -2509,6 +2673,40 @@ } } + private ValueNode processCalleeReturn(ResolvedJavaMethod targetMethod, InliningScope inliningScope, List calleeReturnDataList) { + if (calleeReturnDataList == null) { + /* Callee does not return. */ + lastInstr = null; + } else { + ValueNode calleeReturnValue; + MergeNode returnMergeNode = null; + if (inliningScope != null) { + inliningScope.returnDataList = calleeReturnDataList; + } + if (calleeReturnDataList.size() == 1) { + /* Callee has a single return, we can continue parsing at that point. */ + ReturnToCallerData singleReturnData = calleeReturnDataList.get(0); + lastInstr = singleReturnData.beforeReturnNode; + calleeReturnValue = singleReturnData.returnValue; + } else { + assert calleeReturnDataList.size() > 1; + /* Callee has multiple returns, we need to insert a control flow merge. */ + returnMergeNode = graph.add(new MergeNode()); + calleeReturnValue = ValueMergeUtil.mergeValueProducers(returnMergeNode, calleeReturnDataList, returnData -> returnData.beforeReturnNode, returnData -> returnData.returnValue); + } + + if (calleeReturnValue != null) { + frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue); + } + if (returnMergeNode != null) { + returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode)); + lastInstr = finishInstruction(returnMergeNode, frameState); + } + return calleeReturnValue; + } + return null; + } + public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) { return new MethodCallTargetNode(invokeKind, targetMethod, args, returnStamp, profile); } @@ -2566,7 +2764,7 @@ /* * This must be the return value from within a partial intrinsification. */ - assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci); + assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci) || intrinsicContext.isDeferredInvoke(stateSplit); } } else { assert stateAfter == null; @@ -2628,6 +2826,9 @@ append(new FinalFieldBarrierNode(entryBCI == INVOCATION_ENTRY_BCI ? originalReceiver : null)); } synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x, kind); + if (method.isSynchronized()) { + finishPrepare(lastInstr, BytecodeFrame.AFTER_BCI, frameState); + } } protected MonitorEnterNode createMonitorEnterNode(ValueNode x, MonitorIdNode monitorId) { @@ -2641,7 +2842,7 @@ monitorEnter.setStateAfter(createFrameState(bci, monitorEnter)); } - protected void genMonitorExit(ValueNode x, ValueNode escapedReturnValue, int bci) { + protected void genMonitorExit(ValueNode x, ValueNode escapedValue, int bci) { if (frameState.lockDepth(false) == 0) { throw bailout("unbalanced monitors: too many exits"); } @@ -2650,7 +2851,7 @@ if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject))); } - MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedReturnValue)); + MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedValue)); monitorExit.setStateAfter(createFrameState(bci, monitorExit)); } @@ -2760,7 +2961,7 @@ } } - private Target checkLoopExit(FixedNode target, BciBlock targetBlock, FrameStateBuilder state) { + private Target checkLoopExit(Target target, BciBlock targetBlock) { if (currentBlock != null) { long exits = currentBlock.loops & ~targetBlock.loops; if (exits != 0) { @@ -2790,7 +2991,7 @@ if (targetBlock instanceof ExceptionDispatchBlock) { bci = ((ExceptionDispatchBlock) targetBlock).deoptBci; } - FrameStateBuilder newState = state.copy(); + FrameStateBuilder newState = target.state.copy(); for (BciBlock loop : exitLoops) { LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(loop); LoopExitNode loopExit = graph.add(new LoopExitNode(loopBegin)); @@ -2807,11 +3008,49 @@ loopExit.setStateAfter(newState.create(bci, loopExit)); } - lastLoopExit.setNext(target); - return new Target(firstLoopExit, newState); + // Fortify: Suppress Null Dereference false positive + assert lastLoopExit != null; + + if (target.originalEntry == null) { + lastLoopExit.setNext(target.entry); + return new Target(firstLoopExit, newState, target.entry); + } else { + target.originalEntry.replaceAtPredecessor(firstLoopExit); + lastLoopExit.setNext(target.originalEntry); + return new Target(target.entry, newState, target.originalEntry); + } } } - return new Target(target, state); + return target; + } + + private Target checkUnwind(FixedNode target, BciBlock targetBlock, FrameStateBuilder state) { + if (targetBlock != blockMap.getUnwindBlock()) { + return new Target(target, state); + } + FrameStateBuilder newState = state; + newState = newState.copy(); + newState.setRethrowException(false); + if (!method.isSynchronized()) { + return new Target(target, newState); + } + FixedWithNextNode originalLast = lastInstr; + FrameStateBuilder originalState = frameState; + BeginNode holder = new BeginNode(); + lastInstr = graph.add(holder); + frameState = newState; + assert frameState.stackSize() == 1; + ValueNode exception = frameState.peekObject(); + synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, exception, JavaKind.Void); + lastInstr.setNext(target); + + lastInstr = originalLast; + frameState = originalState; + + FixedNode result = holder.next(); + holder.setNext(null); + holder.safeDelete(); + return new Target(result, newState, target); } private FrameStateBuilder getEntryState(BciBlock block) { @@ -2856,29 +3095,23 @@ * placeholder that later can be replaced with a MergeNode when we see this block * again. */ - FixedNode targetNode; if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader() && (currentBlock.loops & ~block.loops) == 0) { setFirstInstruction(block, lastInstr); lastInstr = null; } else { setFirstInstruction(block, graph.add(new BeginNode())); } - targetNode = getFirstInstruction(block); - Target target = checkLoopExit(targetNode, block, state); - FixedNode result = target.fixed; + Target target = checkUnwind(getFirstInstruction(block), block, state); + target = checkLoopExit(target, block); + FixedNode result = target.entry; FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state; setEntryState(block, currentEntryState); currentEntryState.clearNonLiveLocals(block, liveness, true); - debug.log("createTarget %s: first visit, result: %s", block, targetNode); + debug.log("createTarget %s: first visit, result: %s", block, result); return result; } - // We already saw this block before, so we have to merge states. - if (!getEntryState(block).isCompatibleWith(state)) { - throw bailout(String.format("stacks do not match on merge from %d into %s; bytecodes would not verify:%nexpect: %s%nactual: %s", bci(), block, getEntryState(block), state)); - } - if (getFirstInstruction(block) instanceof LoopBeginNode) { assert (block.isLoopHeader() && currentBlock.getId() >= block.getId()) : "must be backward branch"; /* @@ -2887,8 +3120,8 @@ */ LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block); LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin)); - Target target = checkLoopExit(loopEnd, block, state); - FixedNode result = target.fixed; + Target target = checkLoopExit(new Target(loopEnd, state), block); + FixedNode result = target.entry; getEntryState(block).merge(loopBegin, target.state); debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); @@ -2927,8 +3160,8 @@ // The EndNode for the newly merged edge. EndNode newEnd = graph.add(new EndNode()); - Target target = checkLoopExit(newEnd, block, state); - FixedNode result = target.fixed; + Target target = checkLoopExit(checkUnwind(newEnd, block, state), block); + FixedNode result = target.entry; getEntryState(block).merge(mergeNode, target.state); mergeNode.addForwardEnd(newEnd); @@ -2993,13 +3226,15 @@ } private void handleUnwindBlock(ExceptionDispatchBlock block) { + if (frameState.lockDepth(false) != 0) { + throw bailout("unbalanced monitors: too few exits exiting frame"); + } + assert !frameState.rethrowException(); + finishPrepare(lastInstr, block.deoptBci, frameState); if (parent == null) { - finishPrepare(lastInstr, block.deoptBci, frameState); - frameState.setRethrowException(false); createUnwind(); } else { - ValueNode exception = frameState.pop(JavaKind.Object); - this.unwindValue = exception; + this.unwindValue = frameState.pop(JavaKind.Object); this.beforeUnwindNode = this.lastInstr; } } @@ -3018,7 +3253,6 @@ @SuppressWarnings("try") private void createUnwind() { assert frameState.stackSize() == 1 : frameState; - synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null); try (DebugCloseable context = openNodeContext(frameState, BytecodeFrame.UNWIND_BCI)) { ValueNode exception = frameState.pop(JavaKind.Object); append(new UnwindNode(exception)); @@ -3029,12 +3263,13 @@ private void synchronizedEpilogue(int bci, ValueNode currentReturnValue, JavaKind currentReturnValueKind) { try (DebugCloseable context = openNodeContext(frameState, bci)) { if (method.isSynchronized()) { - if (currentReturnValue != null) { + if (currentReturnValueKind != JavaKind.Void) { + // we are making a state that should look like the state after the return: + // push the return value on the stack frameState.push(currentReturnValueKind, currentReturnValue); } genMonitorExit(methodSynchronizedObject, currentReturnValue, bci); assert !frameState.rethrowException(); - finishPrepare(lastInstr, bci, frameState); } if (frameState.lockDepth(false) != 0) { throw bailout("unbalanced monitors: too few exits exiting frame"); @@ -4557,7 +4792,7 @@ */ if (resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) { if (parsingIntrinsic()) { - throw new GraalError("Cannot use an assertion within the context of an intrinsic."); + throw new GraalError("Cannot use an assertion within the context of an intrinsic: " + resolvedField); } else if (graphBuilderConfig.omitAssertions()) { frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph)); return; diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -48,6 +48,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; import org.graalvm.compiler.nodeinfo.Verbosity; @@ -390,6 +391,10 @@ assert code.equals(other.code) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds"; + if (rethrowException != other.rethrowException) { + return false; + } + if (stackSize() != other.stackSize()) { return false; } @@ -413,7 +418,7 @@ } public void merge(AbstractMergeNode block, FrameStateBuilder other) { - assert isCompatibleWith(other); + GraalError.guarantee(isCompatibleWith(other), "stacks do not match on merge; bytecodes would not verify:%nexpect: %s%nactual: %s", block, other); for (int i = 0; i < localsSize(); i++) { locals[i] = merge(locals[i], other.locals[i], block); @@ -803,6 +808,12 @@ return result; } + public ValueNode peekObject() { + ValueNode x = xpeek(); + assert verifyKind(JavaKind.Object, x); + return x; + } + /** * Pop the specified number of slots off of this stack and return them as an array of * instructions. diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_currentTimeMillis02.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_currentTimeMillis02.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_currentTimeMillis02.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_currentTimeMillis02.java 2019-04-24 19:25:41.000000000 +0000 @@ -24,34 +24,28 @@ package org.graalvm.compiler.jtt.jdk; -import org.junit.Test; - +import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; -/* +/** + * Checks that the time between 2 successive calls to {@link System#currentTimeMillis()} is less + * than 100 milliseconds at least once in 5_000_000 attempts. */ public class System_currentTimeMillis02 extends JTTTest { - static void m(long[] times) { - times[1] = System.currentTimeMillis() - times[0]; - } - public static boolean test() { - long[] times = new long[2]; // { start, delta } - times[0] = System.currentTimeMillis(); - times[1] = 0; - // force compilation: - for (int i = 0; i < 5000; i++) { - m(times); + for (int i = 0; i < 5_000_000; i++) { + long elapsed = System.currentTimeMillis() - System.currentTimeMillis(); + if (elapsed < 100) { + return true; + } } - times[0] = System.currentTimeMillis(); - times[1] = 0; - for (int i = 0; times[1] == 0 && i < 5000000; i++) { - m(times); - // do nothing. + if (!GraalDirectives.inCompiledCode()) { + // We don't care about the result for the interpreter, C1 or C2 + return true; } - // better get at least 100 millisecond resolution. - return times[1] >= 1 && times[1] < 100; + return false; } @Test diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_nanoTime02.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_nanoTime02.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_nanoTime02.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_nanoTime02.java 2019-04-24 19:25:41.000000000 +0000 @@ -24,38 +24,32 @@ package org.graalvm.compiler.jtt.jdk; -import org.junit.Test; - +import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; -/* +/** + * Checks that the time between 2 successive calls to {@link System#nanoTime()} is less than 30 + * microseconds at least once in 5_000_000 attempts. */ public class System_nanoTime02 extends JTTTest { public static boolean test() { - long minDelta = Long.MAX_VALUE; - - // the first call to System.nanoTime might take a long time due to call resolution - for (int c = 0; c < 10; c++) { - long start = System.nanoTime(); - long delta = 0; - int i; - for (i = 0; delta == 0 && i < 50000; i++) { - delta = System.nanoTime() - start; - // do nothing. - } - if (delta < minDelta) { - minDelta = delta; + for (int i = 0; i < 5_000_000; i++) { + long delta = System.nanoTime() - System.nanoTime(); + if (delta < 30_000) { + return true; } } - - // better get at least 30 microsecond resolution. - return minDelta > 1 && minDelta < 30000; + if (!GraalDirectives.inCompiledCode()) { + // We don't care about the result for the interpreter, C1 or C2 + return true; + } + return false; } @Test public void run0() throws Throwable { runTest("test"); } - } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_log10.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_log10.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_log10.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_log10.java 2019-04-24 19:25:41.000000000 +0000 @@ -182,7 +182,7 @@ // Test for gross inaccuracy by comparing to log; should be // within a few ulps of log(x)/log(10) Random rand = new java.util.Random(0L); - for (int i = 0; i < 10000; i++) { + for (int i = 0; i < 500; i++) { double input = Double.longBitsToDouble(rand.nextLong()); if (!Double.isFinite(input)) { continue; // avoid testing NaN and infinite values diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.java 2019-04-24 19:25:41.000000000 +0000 @@ -31,7 +31,7 @@ public abstract class UnaryMath extends JTTTest { - private static final long STEP = Long.MAX_VALUE / 1_000_000; + private static final long STEP = Long.MAX_VALUE / 100_000; /** * Tests a unary {@link Math} method on a wide range of values. diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java 2019-04-24 19:25:41.000000000 +0000 @@ -44,6 +44,7 @@ protected Object object = new Object(); protected volatile boolean drained = false; protected volatile boolean someBoolean = true; + protected volatile int someInt = 3; public boolean test() { boolean b = true; @@ -63,4 +64,49 @@ runTest("test"); } + public synchronized boolean test1() { + boolean b = true; + while (!drained) { + synchronized (object) { + boolean c = b = someBoolean; + if (c || drained) { + break; + } + } + } + return b; + } + + @Test + public void run1() throws Throwable { + runTest("test1"); + } + + public synchronized boolean test2() { + boolean b = true; + while (!drained) { + synchronized (object) { + boolean c = b = someBoolean; + if (c || drained) { + break; + } + if (someInt > 0) { + throw new RuntimeException(); + } + } + if (someInt < -10) { + throw new IndexOutOfBoundsException(); + } + } + if (someInt < -5) { + throw new IllegalArgumentException(); + } + return b; + } + + @Test + public void run2() throws Throwable { + runTest("test2"); + } + } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedParserInlineTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedParserInlineTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedParserInlineTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedParserInlineTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + */ + + +package org.graalvm.compiler.jtt.threads; + +import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; + +public final class SynchronizedParserInlineTest extends JTTTest { + + private static SynchronizedParserInlineTest object = new SynchronizedParserInlineTest(); + + public static Integer test(boolean b) { + foo(object); + return b ? 42 : 1337; + } + + @BytecodeParserForceInline + public static synchronized void foo(SynchronizedParserInlineTest o) { + o.notifyAll(); + } + + @Test + public void run0() { + runTest("test", false); + } + + public static Integer test1(int b) { + return foo1(b); + } + + @BytecodeParserForceInline + public static synchronized int foo1(int b) { + if (b < 0) { + return 7777; + } else if (b > 100) { + throw new RuntimeException(); + } else { + throw new IllegalArgumentException(); + } + } + + @Test + public void run1() { + runTest("test1", -1); + runTest("test1", 1); + runTest("test1", 101); + } + + public static Integer test2(int b) { + return foo2(b); + } + + @BytecodeParserForceInline + public static int foo2(int b) { + if (b < 0) { + return 7777; + } else if (b > 100) { + throw new RuntimeException(); + } else { + throw new IllegalArgumentException(); + } + } + + @Test + public void run2() { + runTest("test2", -1); + runTest("test2", 1); + runTest("test2", 101); + } + +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java 2019-04-24 19:25:41.000000000 +0000 @@ -878,6 +878,9 @@ break; } + // Fortify: Suppress Null Dereference false positive + assert reg != null; + boolean needSplit = blockPos[reg.number] <= intervalTo; int splitPos = blockPos[reg.number]; diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -598,8 +598,8 @@ if (label != null) { labelBindLirPositions.put(label, instructionPosition); } - lirPositions.put(op, instructionPosition); } + lirPositions.put(op, instructionPosition); instructionPosition++; } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java 2019-04-24 19:25:41.000000000 +0000 @@ -278,7 +278,8 @@ } if (cost.getNumMaterializations() > 1 || cost.getBestCost() < tree.getBlock().getRelativeFrequency()) { - try (DebugContext.Scope s = debug.scope("CLOmodify", constTree); Indent i = debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString())) { + try (DebugContext.Scope s = debug.scope("CLOmodify", constTree); + Indent i = debug.isLogEnabled() ? debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString()) : null) { // mark original load for removal deleteInstruction(tree); constantsOptimized.increment(debug); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,17 +24,22 @@ package org.graalvm.compiler.lir.aarch64; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; /** * Bit manipulation ops for ARMv8 ISA. @@ -45,6 +50,7 @@ BSR, BSWP, CLZ, + POPCNT, } private static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64BitManipulationOp.class); @@ -53,11 +59,14 @@ @Def protected AllocatableValue result; @Use({REG}) protected AllocatableValue input; - public AArch64BitManipulationOp(BitManipulationOpCode opcode, AllocatableValue result, AllocatableValue input) { + @Temp({REG, ILLEGAL}) protected Value temp; + + public AArch64BitManipulationOp(LIRGeneratorTool tool, BitManipulationOpCode opcode, AllocatableValue result, AllocatableValue input) { super(TYPE); this.opcode = opcode; this.result = result; this.input = input; + this.temp = BitManipulationOpCode.POPCNT == opcode ? tool.newVariable(LIRKind.value(AArch64Kind.V64_BYTE)) : Value.ILLEGAL; } @Override @@ -83,6 +92,11 @@ case BSWP: masm.rev(size, dst, src); break; + case POPCNT: + assert !Value.ILLEGAL.equals(temp) : "Auxiliary register not allocated."; + Register vreg = asRegister(temp); + masm.popcnt(size, dst, src, vreg); + break; default: throw GraalError.shouldNotReachHere(); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java 2019-04-24 19:25:41.000000000 +0000 @@ -175,7 +175,10 @@ boolean isFarBranch; if (label.isBound()) { - isFarBranch = NumUtil.isSignedNbit(18, masm.position() - label.position()); + // The label.position() is a byte based index. The TBZ instruction has 14 bits for + // the offset and AArch64 instruction is 4 bytes aligned. So TBZ can encode 16 bits + // signed offset. + isFarBranch = !NumUtil.isSignedNbit(16, masm.position() - label.position()); } else { // Max range of tbz is +-2^13 instructions. We estimate that each LIR instruction // emits 2 AArch64 instructions on average. Thus we test for maximum 2^12 LIR diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java 2019-04-24 19:25:41.000000000 +0000 @@ -497,7 +497,12 @@ masm.fmov(32, dst, scratch); } } else { - masm.fldr(32, dst, (AArch64Address) crb.asFloatConstRef(input)); + try (ScratchRegister scr = masm.getScratchRegister()) { + Register scratch = scr.getRegister(); + crb.asFloatConstRef(input); + masm.addressOf(scratch); + masm.fldr(32, dst, AArch64Address.createBaseRegisterOnlyAddress(scratch)); + } } break; case Double: @@ -510,7 +515,12 @@ masm.fmov(64, dst, scratch); } } else { - masm.fldr(64, dst, (AArch64Address) crb.asDoubleConstRef(input)); + try (ScratchRegister scr = masm.getScratchRegister()) { + Register scratch = scr.getRegister(); + crb.asDoubleConstRef(input); + masm.addressOf(scratch); + masm.fldr(64, dst, AArch64Address.createBaseRegisterOnlyAddress(scratch)); + } } break; case Object: diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java 2019-04-24 19:25:41.000000000 +0000 @@ -299,7 +299,7 @@ int imm32 = label.position() - jumpTablePos; masm.emitInt(imm32); } else { - label.addPatchAt(masm.position()); + label.addPatchAt(masm.position(), masm); masm.emitByte(0); // pseudo-opcode for jump table entry masm.emitShort(offsetToJumpTableBase); @@ -393,7 +393,7 @@ masm.emitInt(imm32); } else { int offsetToJumpTableBase = masm.position() - jumpTablePos; - label.addPatchAt(masm.position()); + label.addPatchAt(masm.position(), masm); masm.emitByte(0); // pseudo-opcode for jump table entry masm.emitShort(offsetToJumpTableBase); masm.emitByte(0); // padding to make jump table entry 4 bytes wide diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java 2019-04-24 19:25:41.000000000 +0000 @@ -164,7 +164,7 @@ @Override public String toString() { - return (isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + loop().getDepth() + ") " + loopBegin(); + return (countedLoopChecked && isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + loop().getDepth() + ") " + loopBegin(); } private class InvariantPredicate implements NodePredicate { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java 2019-04-24 19:25:41.000000000 +0000 @@ -394,9 +394,14 @@ invariantValue = switchNode.value(); controls = new ArrayList<>(); controls.add(switchNode); - } else if (switchNode.value() == invariantValue && firstSwitch.structureEquals(switchNode)) { - // Only collect switches which test the same values in the same order - controls.add(switchNode); + } else if (switchNode.value() == invariantValue) { + // Fortify: Suppress Null Dereference false positive + assert firstSwitch != null; + + if (firstSwitch.structureEquals(switchNode)) { + // Only collect switches which test the same values in the same order + controls.add(switchNode); + } } } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -289,11 +289,17 @@ } if ((xResidue == 0 && left != null) || (yResidue == 0 && right != null)) { if (left == null) { + // Fortify: Suppress Null Dereference false positive + assert leftCst != null; + left = ConstantNode.forIntegerBits(bits, leftCst.asLong() - min); } else if (xResidue != 0) { left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue), view); } if (right == null) { + // Fortify: Suppress Null Dereference false positive + assert rightCst != null; + right = ConstantNode.forIntegerBits(bits, rightCst.asLong() - min); } else if (yResidue != 0) { right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue), view); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -41,6 +41,7 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; +import org.graalvm.compiler.nodes.type.NarrowOopStamp; import org.graalvm.compiler.nodes.type.StampTool; import jdk.vm.ci.meta.JavaConstant; @@ -67,6 +68,7 @@ public IsNullNode(ValueNode object) { this(object, JavaConstant.NULL_POINTER); + assertNonNarrow(object); } public JavaConstant nullConstant() { @@ -74,9 +76,19 @@ } public static LogicNode create(ValueNode forValue) { + assertNonNarrow(forValue); return canonicalized(null, forValue, JavaConstant.NULL_POINTER); } + public static LogicNode create(ValueNode forValue, JavaConstant nullConstant) { + assert nullConstant.isNull() : "Null constant is not null: " + nullConstant; + return canonicalized(null, forValue, nullConstant); + } + + private static void assertNonNarrow(ValueNode object) { + assert !(object.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) : "Value to compare against null is a NarrowOop" + object; + } + @Override public void generate(NodeLIRBuilderTool gen) { // Nothing to do. diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -138,14 +138,22 @@ } else if (forX.stamp(view).alwaysDistinct(forY.stamp(view))) { return LogicConstantNode.contradiction(); } else if (((AbstractPointerStamp) forX.stamp(view)).alwaysNull()) { - return IsNullNode.create(forY); + return nullSynonym(forY, forX); } else if (((AbstractPointerStamp) forY.stamp(view)).alwaysNull()) { - return IsNullNode.create(forX); + return nullSynonym(forX, forY); } else { return null; } } + private static LogicNode nullSynonym(ValueNode nonNullValue, ValueNode nullValue) { + if (nullValue.isConstant()) { + return IsNullNode.create(nonNullValue, nullValue.asJavaConstant()); + } else { + return IsNullNode.create(nonNullValue); + } + } + @Override public Stamp getSucceedingStampForX(boolean negated, Stamp xStamp, Stamp yStamp) { if (!negated) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CallTargetNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CallTargetNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CallTargetNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CallTargetNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -137,4 +137,8 @@ public void setInvokeKind(InvokeKind kind) { this.invokeKind = kind; } + + public Invoke invoke() { + return (Invoke) this.usages().first(); + } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java 2019-04-24 19:25:41.000000000 +0000 @@ -317,6 +317,9 @@ dominator = ((dominator == null) ? pred : commonDominatorRaw(dominator, pred)); } } + // Fortify: Suppress Null Dereference false positive (every block apart from the first + // is guaranteed to have a predecessor) + assert dominator != null; // Set dominator. block.setDominator(dominator); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -28,6 +28,12 @@ /** * Interface implemented by nodes which may need {@linkplain FrameState deoptimization information}. + *

+ * Sub-interfaces are used to specify exactly when the deoptimization can take place: + * {@linkplain DeoptBefore before}, {@linkplain DeoptAfter after}, and/or {@linkplain DeoptDuring + * during}.
+ * Note that these sub-interfaces are not mutually exclusive so that nodes that may deoptimize at + * multiple times can be modeled. */ public interface DeoptimizingNode extends NodeWithState { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -79,6 +79,13 @@ public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { + if (!foreignCalls.isAvailable(descriptor)) { + // When using encoded snippets a graph main contain a reference to a foreign call that's + // not actually available in the current configuration. It's assumed that further + // simplification of the graph will eliminate this call completely. + return false; + } + ForeignCallNode node = new ForeignCallNode(foreignCalls, descriptor, arguments); node.setStamp(returnStamp); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -39,9 +39,9 @@ @OptionalInput(Guard) protected GuardingNode guard; - public GuardedUnsafeLoadNode(ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity, GuardingNode guard) { + public GuardedUnsafeLoadNode(ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity, ValueNode guard) { super(TYPE, object, offset, accessKind, locationIdentity); - this.guard = guard; + this.guard = (GuardingNode) guard; } @Override @@ -54,4 +54,7 @@ updateUsagesInterface(this.guard, guard); this.guard = guard; } + + @NodeIntrinsic + public static native Object guardedLoad(Object object, long offset, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity, GuardingNode guard); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java 2019-04-24 19:25:41.000000000 +0000 @@ -45,6 +45,8 @@ */ public abstract class GeneratedInvocationPlugin implements InvocationPlugin { + private ResolvedJavaMethod executeMethod; + /** * Gets the class of the annotation for which this plugin was generated. */ @@ -69,23 +71,37 @@ return true; } - if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) { + if (IS_IN_NATIVE_IMAGE) { // The reflection here is problematic for SVM. return true; } - MetaAccessProvider metaAccess = b.getMetaAccess(); - ResolvedJavaMethod executeMethod = metaAccess.lookupJavaMethod(getExecuteMethod()); - ResolvedJavaType thisClass = metaAccess.lookupJavaType(getClass()); - ResolvedJavaMethod thisExecuteMethod = thisClass.resolveConcreteMethod(executeMethod, thisClass); + if (b.getMethod().equals(foldAnnotatedMethod)) { + return false; + } + + ResolvedJavaMethod thisExecuteMethod = getExecutedMethod(b); if (b.getMethod().equals(thisExecuteMethod)) { // The "execute" method of this plugin is itself being compiled. In (only) this context, // the injected argument of the call to the @Fold annotated method will be non-null. + if (IS_BUILDING_NATIVE_IMAGE) { + return false; + } return true; } throw new AssertionError("must pass null to injected argument of " + foldAnnotatedMethod.format("%H.%n(%p)") + ", not " + arg); } + private ResolvedJavaMethod getExecutedMethod(GraphBuilderContext b) { + if (executeMethod == null) { + MetaAccessProvider metaAccess = b.getMetaAccess(); + ResolvedJavaMethod baseMethod = metaAccess.lookupJavaMethod(getExecuteMethod()); + ResolvedJavaType thisClass = metaAccess.lookupJavaType(getClass()); + executeMethod = thisClass.resolveConcreteMethod(baseMethod, thisClass); + } + return executeMethod; + } + private static Method getExecuteMethod() { try { return GeneratedInvocationPlugin.class.getMethod("execute", GraphBuilderContext.class, ResolvedJavaMethod.class, InvocationPlugin.Receiver.class, ValueNode[].class); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java 2019-04-24 19:25:41.000000000 +0000 @@ -47,6 +47,7 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StateSplit; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IsNullNode; import org.graalvm.compiler.nodes.calc.NarrowNode; @@ -165,6 +166,19 @@ boolean intrinsify(BytecodeProvider bytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver); /** + * Intrinsifies an invocation of a given method by inlining the graph of a given substitution + * method. + * + * @param targetMethod the method being intrinsified + * @param substituteGraph the intrinsic implementation + * @param receiver the receiver, or null for static methods + * @param argsIncludingReceiver the arguments with which to inline the invocation + * + * @return whether the intrinsification was successful + */ + boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver); + + /** * Creates a snap shot of the current frame state with the BCI of the instruction after the one * currently being parsed and assigns it to a given {@linkplain StateSplit#hasSideEffect() side * effect} node. diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java 2019-04-24 19:25:41.000000000 +0000 @@ -47,35 +47,43 @@ * Denotes a call site that must not be inlined and should be implemented by a node that * does not speculate on the call not raising an exception. */ - public static final InlineInfo DO_NOT_INLINE_WITH_EXCEPTION = new InlineInfo(null, null, null); + public static final InlineInfo DO_NOT_INLINE_WITH_EXCEPTION = new InlineInfo(); /** * Denotes a call site must not be inlined and can be implemented by a node that speculates * the call will not throw an exception. */ - public static final InlineInfo DO_NOT_INLINE_NO_EXCEPTION = new InlineInfo(null, null, null); + public static final InlineInfo DO_NOT_INLINE_NO_EXCEPTION = new InlineInfo(); /** * Denotes a call site must not be inlined and the execution should be transferred to * interpreter in case of an exception. */ - public static final InlineInfo DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION = new InlineInfo(null, null, null); + public static final InlineInfo DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION = new InlineInfo(); private final ResolvedJavaMethod methodToInline; - private final ResolvedJavaMethod originalMethod; + private final MethodSubstitutionPlugin plugin; private final BytecodeProvider intrinsicBytecodeProvider; public static InlineInfo createStandardInlineInfo(ResolvedJavaMethod methodToInline) { return new InlineInfo(methodToInline, null, null); } - public static InlineInfo createIntrinsicInlineInfo(ResolvedJavaMethod methodToInline, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider) { - return new InlineInfo(methodToInline, originalMethod, intrinsicBytecodeProvider); + public static InlineInfo createIntrinsicInlineInfo(ResolvedJavaMethod methodToInline, BytecodeProvider intrinsicBytecodeProvider) { + return new InlineInfo(methodToInline, null, intrinsicBytecodeProvider); } - private InlineInfo(ResolvedJavaMethod methodToInline, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider) { + public static InlineInfo createMethodSubstitutionInlineInfo(ResolvedJavaMethod methodToInline, MethodSubstitutionPlugin plugin) { + return new InlineInfo(methodToInline, plugin, plugin.getBytecodeProvider()); + } + + private InlineInfo() { + this(null, null, null); + } + + private InlineInfo(ResolvedJavaMethod methodToInline, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider) { this.methodToInline = methodToInline; - this.originalMethod = originalMethod; + this.plugin = plugin; this.intrinsicBytecodeProvider = intrinsicBytecodeProvider; } @@ -91,14 +99,6 @@ } /** - * Returns the original method if this is an inline of an intrinsic, or {@code null} if the - * call site must not be inlined. - */ - public ResolvedJavaMethod getOriginalMethod() { - return originalMethod; - } - - /** * Gets the provider of bytecode to be parsed for {@link #getMethodToInline()} if is is an * intrinsic for the original method (i.e., the {@code method} passed to * {@link InlineInvokePlugin#shouldInlineInvoke}). A {@code null} return value indicates @@ -107,6 +107,14 @@ public BytecodeProvider getIntrinsicBytecodeProvider() { return intrinsicBytecodeProvider; } + + public boolean isSubstitution() { + return plugin != null; + } + + public MethodSubstitutionPlugin getPlugin() { + return plugin; + } } /** diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java 2019-04-24 19:25:41.000000000 +0000 @@ -191,6 +191,11 @@ void addSideEffect(StateSplit sideEffect); } + @SuppressWarnings("unused") + public boolean isDeferredInvoke(StateSplit stateSplit) { + return false; + } + public FrameState createFrameState(StructuredGraph graph, SideEffectsState sideEffects, StateSplit forStateSplit, NodeSourcePosition sourcePosition) { assert forStateSplit != graph.start(); if (forStateSplit.hasSideEffect()) { @@ -205,12 +210,16 @@ lastSideEffect.setStateAfter(invalid); } } - sideEffects.addSideEffect(forStateSplit); FrameState frameState; - if (forStateSplit instanceof ExceptionObjectNode) { - frameState = graph.add(new FrameState(AFTER_EXCEPTION_BCI, (ExceptionObjectNode) forStateSplit)); + if (isDeferredInvoke(forStateSplit)) { + frameState = graph.add(new FrameState(INVALID_FRAMESTATE_BCI)); } else { - frameState = graph.add(new FrameState(AFTER_BCI)); + sideEffects.addSideEffect(forStateSplit); + if (forStateSplit instanceof ExceptionObjectNode) { + frameState = graph.add(new FrameState(AFTER_EXCEPTION_BCI, (ExceptionObjectNode) forStateSplit)); + } else { + frameState = graph.add(new FrameState(AFTER_BCI)); + } } if (graph.trackNodeSourcePosition()) { frameState.setNodeSourcePosition(sourcePosition); @@ -243,6 +252,7 @@ @Override public String toString() { - return "Intrinsic{original: " + originalMethod.format("%H.%n(%p)") + ", intrinsic: " + intrinsicMethod.format("%H.%n(%p)") + ", context: " + compilationContext + "}"; + return "Intrinsic{original: " + originalMethod.format("%H.%n(%p)") + ", intrinsic: " + (intrinsicMethod != null ? intrinsicMethod.format("%H.%n(%p)") : "null") + ", context: " + + compilationContext + "}"; } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -197,6 +197,11 @@ return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]); } else if (argsIncludingReceiver.length == 5) { return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]); + } else if (argsIncludingReceiver.length == 6) { + return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4], argsIncludingReceiver[5]); + } else if (argsIncludingReceiver.length == 7) { + return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4], argsIncludingReceiver[5], + argsIncludingReceiver[6]); } else { return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java 2019-04-24 19:25:41.000000000 +0000 @@ -1023,18 +1023,10 @@ if (parent != null) { InvocationPlugin plugin = parent.lookupInvocation(method); if (plugin != null) { - if (IS_IN_NATIVE_IMAGE && plugin instanceof MethodSubstitutionPlugin) { - // Disable method substitutions until GR-13607 - return null; - } return plugin; } } InvocationPlugin invocationPlugin = get(method); - if (IS_IN_NATIVE_IMAGE && invocationPlugin instanceof MethodSubstitutionPlugin) { - // Disable method substitutions until GR-13607 - return null; - } return invocationPlugin; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,6 +25,8 @@ package org.graalvm.compiler.nodes.graphbuilderconf; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; +import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; +import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import static org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.resolveType; import java.lang.reflect.Method; @@ -35,6 +37,7 @@ import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.meta.MetaAccessProvider; @@ -116,9 +119,16 @@ } /** + * Gets the class in which the substitute method is declared. + */ + public Class getDeclaringClass() { + return declaringClass; + } + + /** * Gets the reflection API version of the substitution method. */ - Method getJavaSubstitute() throws GraalError { + public Method getJavaSubstitute() throws GraalError { Method substituteMethod = lookupSubstitute(); int modifiers = substituteMethod.getModifiers(); if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { @@ -178,12 +188,18 @@ @Override public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { - if (IS_IN_NATIVE_IMAGE) { - // these are currently unimplemented - return false; + if (IS_IN_NATIVE_IMAGE || (UseEncodedGraphs.getValue(b.getOptions()) && !b.parsingIntrinsic())) { + if (!IS_IN_NATIVE_IMAGE && UseEncodedGraphs.getValue(b.getOptions())) { + b.getReplacements().registerMethodSubstitution(this, targetMethod, INLINE_AFTER_PARSING, b.getOptions()); + } + StructuredGraph subst = b.getReplacements().getMethodSubstitution(this, targetMethod, INLINE_AFTER_PARSING, StructuredGraph.AllowAssumptions.ifNonNull(b.getAssumptions()), b.getOptions()); + if (subst == null) { + throw new GraalError("No graphs found for substitution %s", this); + } + return b.intrinsify(targetMethod, subst, receiver, argsIncludingReceiver); } - ResolvedJavaMethod subst = getSubstitute(b.getMetaAccess()); - return b.intrinsify(bytecodeProvider, targetMethod, subst, receiver, argsIncludingReceiver); + ResolvedJavaMethod substitute = getSubstitute(b.getMetaAccess()); + return b.intrinsify(bytecodeProvider, targetMethod, substitute, receiver, argsIncludingReceiver); } @Override diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java 2019-04-24 19:25:41.000000000 +0000 @@ -878,33 +878,37 @@ registerNode(outerScope, proxyOrderId, phiInput, true, false); replacement = phiInput; - } else if (!merge.isPhiAtMerge(existing)) { - /* Now we have two different values, so we need to create a phi node. */ - PhiNode phi; - if (proxy instanceof ValueProxyNode) { - phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(NodeView.DEFAULT), merge)); - } else if (proxy instanceof GuardProxyNode) { - phi = graph.addWithoutUnique(new GuardPhiNode(merge)); + } else { + // Fortify: Suppress Null Dereference false positive + assert merge != null; + + if (!merge.isPhiAtMerge(existing)) { + /* Now we have two different values, so we need to create a phi node. */ + PhiNode phi; + if (proxy instanceof ValueProxyNode) { + phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(NodeView.DEFAULT), merge)); + } else if (proxy instanceof GuardProxyNode) { + phi = graph.addWithoutUnique(new GuardPhiNode(merge)); + } else { + throw GraalError.shouldNotReachHere(); + } + /* Add the inputs from all previous exits. */ + for (int j = 0; j < merge.phiPredecessorCount() - 1; j++) { + phi.addInput(existing); + } + /* Add the input from this exit. */ + phi.addInput(phiInput); + registerNode(outerScope, proxyOrderId, phi, true, false); + replacement = phi; + phiCreated = true; + } else { - throw GraalError.shouldNotReachHere(); + /* Phi node has been created before, so just add the new input. */ + PhiNode phi = (PhiNode) existing; + phi.addInput(phiInput); + replacement = phi; } - /* Add the inputs from all previous exits. */ - for (int j = 0; j < merge.phiPredecessorCount() - 1; j++) { - phi.addInput(existing); - } - /* Add the input from this exit. */ - phi.addInput(phiInput); - registerNode(outerScope, proxyOrderId, phi, true, false); - replacement = phi; - phiCreated = true; - - } else { - /* Phi node has been created before, so just add the new input. */ - PhiNode phi = (PhiNode) existing; - phi.addInput(phiInput); - replacement = phi; } - proxy.replaceAtUsagesAndDelete(replacement); } @@ -1814,6 +1818,7 @@ } } assert loopVariableIndex != -1; + assert explosionHeadValue != null; ValuePhiNode loopVariablePhi; SortedMap dispatchTable = new TreeMap<>(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -768,6 +768,9 @@ removeThroughFalseBranch(tool, merge); return true; } else if (distinct == 1) { + // Fortify: Suppress Null Dereference false positive + assert singlePhi != null; + ValueNode trueValue = singlePhi.valueAt(trueEnd); ValueNode falseValue = singlePhi.valueAt(falseEnd); ValueNode conditional = canonicalizeConditionalCascade(tool, trueValue, falseValue); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java 2019-04-24 19:25:41.000000000 +0000 @@ -118,4 +118,6 @@ default InvokeKind getInvokeKind() { return callTarget().invokeKind(); } + + void replaceBci(int newBci); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -55,6 +55,7 @@ import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider; import jdk.internal.vm.compiler.word.LocationIdentity; +import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.JavaKind; /** @@ -76,7 +77,7 @@ @OptionalInput ValueNode classInit; @Input(Extension) CallTargetNode callTarget; @OptionalInput(State) FrameState stateDuring; - protected final int bci; + protected int bci; protected boolean polymorphic; protected boolean useForInlining; protected final LocationIdentity identity; @@ -102,15 +103,19 @@ this.identity = identity; } - public InvokeNode replaceWithNewBci(int newBci) { - InvokeNode newInvoke = graph().add(new InvokeNode(callTarget, newBci, stamp, identity)); - newInvoke.setUseForInlining(useForInlining); - newInvoke.setPolymorphic(polymorphic); - newInvoke.setStateAfter(stateAfter); - newInvoke.setStateDuring(stateDuring); - newInvoke.setClassInit(classInit); - graph().replaceFixedWithFixed(this, newInvoke); - return newInvoke; + public InvokeNode(InvokeWithExceptionNode invoke) { + super(TYPE, invoke.stamp); + this.callTarget = invoke.callTarget; + this.bci = invoke.bci; + this.polymorphic = invoke.polymorphic; + this.useForInlining = invoke.useForInlining; + this.identity = invoke.getLocationIdentity(); + } + + @Override + public void replaceBci(int newBci) { + assert BytecodeFrame.isPlaceholderBci(bci) && !BytecodeFrame.isPlaceholderBci(newBci) : "can only replace placeholder with better bci"; + bci = newBci; } @Override diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -24,7 +24,16 @@ package org.graalvm.compiler.nodes; +import static org.graalvm.compiler.nodeinfo.InputType.Extension; +import static org.graalvm.compiler.nodeinfo.InputType.Memory; +import static org.graalvm.compiler.nodeinfo.InputType.State; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; + +import java.util.Map; + import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -38,13 +47,7 @@ import org.graalvm.compiler.nodes.util.GraphUtil; import jdk.internal.vm.compiler.word.LocationIdentity; -import java.util.Map; - -import static org.graalvm.compiler.nodeinfo.InputType.Extension; -import static org.graalvm.compiler.nodeinfo.InputType.Memory; -import static org.graalvm.compiler.nodeinfo.InputType.State; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; +import jdk.vm.ci.code.BytecodeFrame; @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}", allowedUsageTypes = {Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) public final class InvokeWithExceptionNode extends ControlSplitNode implements Invoke, MemoryCheckpoint.Single, LIRLowerable, UncheckedInterfaceProvider { @@ -58,7 +61,7 @@ @Input(Extension) CallTargetNode callTarget; @OptionalInput(State) FrameState stateDuring; @OptionalInput(State) FrameState stateAfter; - protected final int bci; + protected int bci; protected boolean polymorphic; protected boolean useForInlining; protected double exceptionProbability; @@ -207,20 +210,25 @@ GraphUtil.killCFG(edge); } - public void replaceWithNewBci(int newBci) { - AbstractBeginNode nextNode = next(); - AbstractBeginNode exceptionObject = exceptionEdge; - setExceptionEdge(null); - setNext(null); - InvokeWithExceptionNode repl = graph().add(new InvokeWithExceptionNode(callTarget(), exceptionObject, newBci)); - repl.setStateAfter(stateAfter); - this.setStateAfter(null); - this.replaceAtPredecessor(repl); - repl.setNext(nextNode); - boolean removed = this.callTarget().removeUsage(this); - assert removed; - this.replaceAtUsages(repl); - this.markDeleted(); + @SuppressWarnings("try") + public AbstractBeginNode killKillingBegin() { + AbstractBeginNode begin = next(); + if (begin instanceof KillingBeginNode) { + try (DebugCloseable position = begin.withNodeSourcePosition()) { + AbstractBeginNode newBegin = new BeginNode(); + graph().addAfterFixed(begin, graph().add(newBegin)); + begin.replaceAtUsages(newBegin); + graph().removeFixed(begin); + return newBegin; + } + } + return begin; + } + + @Override + public void replaceBci(int newBci) { + assert BytecodeFrame.isPlaceholderBci(bci) && !BytecodeFrame.isPlaceholderBci(newBci) : "can only replace placeholder with better bci"; + bci = newBci; } @Override diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -95,10 +95,6 @@ return targetMethod().getSignature().getReturnKind(); } - public Invoke invoke() { - return (Invoke) this.usages().first(); - } - @Override public boolean verify() { assert getUsageCount() <= 1 : "call target may only be used by a single invoke"; diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -56,15 +56,15 @@ */ @OptionalInput ValueNode escapedReturnValue; - public MonitorExitNode(ValueNode object, MonitorIdNode monitorId, ValueNode escapedReturnValue) { + public MonitorExitNode(ValueNode object, MonitorIdNode monitorId, ValueNode escapedValue) { super(TYPE, object, monitorId); - this.escapedReturnValue = escapedReturnValue; + this.escapedReturnValue = escapedValue; } /** * Return value is cleared when a synchronized method graph is inlined. */ - public void clearEscapedReturnValue() { + public void clearEscapedValue() { updateUsages(escapedReturnValue, null); this.escapedReturnValue = null; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -188,11 +188,10 @@ } } + ArrayList oldSuccessors = new ArrayList<>(); for (int i = 0; i < blockSuccessorCount(); i++) { AbstractBeginNode successor = blockSuccessor(i); - if (!newSuccessors.contains(successor)) { - tool.deleteBranch(successor); - } + oldSuccessors.add(successor); setBlockSuccessor(i, null); } @@ -200,6 +199,13 @@ TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors, tool.getConstantReflection())); ((FixedWithNextNode) predecessor()).setNext(newSwitch); GraphUtil.killWithUnusedFloatingInputs(this); + + for (int i = 0; i < oldSuccessors.size(); i++) { + AbstractBeginNode successor = oldSuccessors.get(i); + if (!newSuccessors.contains(successor)) { + GraphUtil.killCFG(successor); + } + } } } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,7 +25,6 @@ package org.graalvm.compiler.nodes.spi; import org.graalvm.compiler.api.replacements.SnippetTemplateCache; -import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.debug.DebugContext; @@ -33,6 +32,8 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; +import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -48,8 +49,8 @@ } @Override - public OptionValues getOptions() { - return delegate.getOptions(); + public CoreProviders getProviders() { + return delegate.getProviders(); } @Override @@ -63,28 +64,30 @@ } @Override - public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { - return delegate.getSnippet(method, args, trackNodeSourcePosition, replaceePosition); + public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, + OptionValues options) { + return delegate.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition, options); } @Override - public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { - return delegate.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition); + public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { + delegate.registerSnippet(method, original, receiver, trackNodeSourcePosition, options); } @Override - public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { - delegate.registerSnippet(method, original, receiver, trackNodeSourcePosition); + public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, + StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { + return delegate.getMethodSubstitution(plugin, original, context, allowAssumptions, options); } @Override - public StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { - return delegate.getSubstitution(method, invokeBci, trackNodeSourcePosition, replaceePosition); + public void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { + delegate.registerMethodSubstitution(plugin, original, context, options); } @Override - public Bytecode getSubstitutionBytecode(ResolvedJavaMethod method) { - return delegate.getSubstitutionBytecode(method); + public StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { + return delegate.getSubstitution(method, invokeBci, trackNodeSourcePosition, replaceePosition, options); } @Override diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java 2019-04-24 19:25:41.000000000 +0000 @@ -26,7 +26,6 @@ import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.api.replacements.SnippetTemplateCache; -import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.debug.DebugContext; @@ -34,7 +33,9 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -44,7 +45,7 @@ */ public interface Replacements { - OptionValues getOptions(); + CoreProviders getProviders(); /** * Gets the object managing the various graph builder plugins used by this object when parsing @@ -60,30 +61,41 @@ /** * Gets the snippet graph derived from a given method. * - * @param args arguments to the snippet if available, otherwise {@code null} - * @param trackNodeSourcePosition - * @return the snippet graph, if any, that is derived from {@code method} - */ - default StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { - return getSnippet(method, null, args, trackNodeSourcePosition, replaceePosition); - } - - /** - * Gets the snippet graph derived from a given method. - * * @param recursiveEntry if the snippet contains a call to this method, it's considered as * recursive call and won't be processed for {@linkplain MethodSubstitution * substitutions}. * @param args arguments to the snippet if available, otherwise {@code null} * @param trackNodeSourcePosition + * @param options * @return the snippet graph, if any, that is derived from {@code method} */ - StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition); + StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, + OptionValues options); /** * Registers a method as snippet. */ - void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition); + void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options); + + /** + * Gets a graph that is a substitution for a given {@link MethodSubstitutionPlugin plugin} in + * the {@link org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext + * context}. + * + * @param plugin the plugin being substituted + * @param original the method being substituted + * @param context the kind of inlining to be performed for the substitution + * @param allowAssumptions + * @param options + * @return the method substitution graph, if any, that is derived from {@code method} + */ + StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, + StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options); + + /** + * Registers a plugin as a substitution. + */ + void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options); /** * Gets a graph that is a substitution for a given method. @@ -91,17 +103,10 @@ * @param invokeBci the call site BCI if this request is made for inlining a substitute * otherwise {@code -1} * @param trackNodeSourcePosition + * @param options * @return the graph, if any, that is a substitution for {@code method} */ - StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition); - - /** - * Gets the substitute bytecode for a given method. - * - * @return the bytecode to substitute for {@code method} or {@code null} if there is no - * substitute bytecode for {@code method} - */ - Bytecode getSubstitutionBytecode(ResolvedJavaMethod method); + StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options); /** * Gets a graph produced from the intrinsic for a given method that can be compiled and @@ -116,7 +121,7 @@ /** * Determines if there may be a - * {@linkplain #getSubstitution(ResolvedJavaMethod, int, boolean, NodeSourcePosition) + * {@linkplain #getSubstitution(ResolvedJavaMethod, int, boolean, NodeSourcePosition, OptionValues) * substitution graph} for a given method. * * A call to {@link #getSubstitution} may still return {@code null} for {@code method} and diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java 2019-04-24 19:25:41.000000000 +0000 @@ -966,7 +966,7 @@ */ public List getMethods() { if (methods != null) { - assert checkFrameStatesAgainstInlinedMethods(); + assert isSubstitution || checkFrameStatesAgainstInlinedMethods(); return Collections.unmodifiableList(methods); } return Collections.emptyList(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java 2019-04-24 19:25:41.000000000 +0000 @@ -243,10 +243,12 @@ EconomicSet unsafeNodes = null; Graph.NodeEventScope nodeEventScope = null; OptionValues options = node.getOptions(); - if (Graph.Options.VerifyGraalGraphEdges.getValue(options)) { + boolean verifyGraalGraphEdges = Graph.Options.VerifyGraalGraphEdges.getValue(options); + boolean verifyKillCFGUnusedNodes = GraphUtil.Options.VerifyKillCFGUnusedNodes.getValue(options); + if (verifyGraalGraphEdges) { unsafeNodes = collectUnsafeNodes(node.graph()); } - if (GraphUtil.Options.VerifyKillCFGUnusedNodes.getValue(options)) { + if (verifyKillCFGUnusedNodes) { EconomicSet collectedUnusedNodes = unusedNodes = EconomicSet.create(Equivalence.IDENTITY); nodeEventScope = node.graph().trackNodeEvents(new Graph.NodeEventListener() { @Override @@ -260,12 +262,12 @@ debug.dump(DebugContext.VERY_DETAILED_LEVEL, node.graph(), "Before killCFG %s", node); killCFGInner(node); debug.dump(DebugContext.VERY_DETAILED_LEVEL, node.graph(), "After killCFG %s", node); - if (Graph.Options.VerifyGraalGraphEdges.getValue(options)) { + if (verifyGraalGraphEdges) { EconomicSet newUnsafeNodes = collectUnsafeNodes(node.graph()); newUnsafeNodes.removeAll(unsafeNodes); assert newUnsafeNodes.isEmpty() : "New unsafe nodes: " + newUnsafeNodes; } - if (GraphUtil.Options.VerifyKillCFGUnusedNodes.getValue(options)) { + if (verifyKillCFGUnusedNodes) { nodeEventScope.close(); Iterator iterator = unusedNodes.iterator(); while (iterator.hasNext()) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java 2019-04-24 19:25:41.000000000 +0000 @@ -511,6 +511,8 @@ allow = true; } } else { + // Fortify: Suppress Null Dereference false positive + assert bestPossibleStamp != null; allow = (bestPossibleStamp.asConstant() != null); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java 2019-04-24 19:25:41.000000000 +0000 @@ -24,6 +24,7 @@ package org.graalvm.compiler.phases.common; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -34,7 +35,6 @@ import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.DynamicDeoptimizeNode; import org.graalvm.compiler.nodes.EndNode; -import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopExitNode; @@ -59,54 +59,53 @@ protected void run(StructuredGraph graph, MidTierContext context) { ControlFlowGraph cfg = null; for (FrameState fs : graph.getNodes(FrameState.TYPE)) { - FixedNode target = null; - PhiNode reasonActionPhi = null; - PhiNode speculationPhi = null; - List obsoletes = null; - for (AbstractDeoptimizeNode deopt : fs.usages().filter(AbstractDeoptimizeNode.class)) { - if (target == null) { - target = deopt; - } else { - if (cfg == null) { - cfg = ControlFlowGraph.compute(graph, true, true, false, false); - } - AbstractMergeNode merge; - if (target instanceof AbstractDeoptimizeNode) { - merge = graph.add(new MergeNode()); - EndNode firstEnd = graph.add(new EndNode()); - ValueNode actionAndReason = ((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess()); - ValueNode speculation = ((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess()); - reasonActionPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(actionAndReason.getStackKind()), merge)); - speculationPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(speculation.getStackKind()), merge)); - merge.addForwardEnd(firstEnd); - reasonActionPhi.addInput(actionAndReason); - speculationPhi.addInput(speculation); - target.replaceAtPredecessor(firstEnd); - - exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg); - try (DebugCloseable position = target.withNodeSourcePosition()) { - merge.setNext(graph.add(new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi))); - } - obsoletes = new LinkedList<>(); - obsoletes.add((AbstractDeoptimizeNode) target); - target = merge; - } else { - merge = (AbstractMergeNode) target; - } - EndNode newEnd = graph.add(new EndNode()); - merge.addForwardEnd(newEnd); - reasonActionPhi.addInput(deopt.getActionAndReason(context.getMetaAccess())); - speculationPhi.addInput(deopt.getSpeculation(context.getMetaAccess())); - deopt.replaceAtPredecessor(newEnd); - exitLoops(deopt, newEnd, cfg); - obsoletes.add(deopt); - } + Iterator iterator = fs.usages().filter(AbstractDeoptimizeNode.class).iterator(); + if (!iterator.hasNext()) { + // No deopt + continue; } - if (obsoletes != null) { - ((DynamicDeoptimizeNode) ((AbstractMergeNode) target).next()).setStateBefore(fs); - for (AbstractDeoptimizeNode obsolete : obsoletes) { - obsolete.safeDelete(); - } + AbstractDeoptimizeNode first = iterator.next(); + if (!iterator.hasNext()) { + // Only 1 deopt + continue; + } + // There is more than one deopt, create a merge + if (cfg == null) { + cfg = ControlFlowGraph.compute(graph, true, true, false, false); + } + AbstractMergeNode merge = graph.add(new MergeNode()); + EndNode firstEnd = graph.add(new EndNode()); + ValueNode actionAndReason = first.getActionAndReason(context.getMetaAccess()); + ValueNode speculation = first.getSpeculation(context.getMetaAccess()); + PhiNode reasonActionPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(actionAndReason.getStackKind()), merge)); + PhiNode speculationPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(speculation.getStackKind()), merge)); + merge.addForwardEnd(firstEnd); + reasonActionPhi.addInput(actionAndReason); + speculationPhi.addInput(speculation); + first.replaceAtPredecessor(firstEnd); + exitLoops(first, firstEnd, cfg); + DynamicDeoptimizeNode dynamicDeopt; + try (DebugCloseable position = first.withNodeSourcePosition()) { + dynamicDeopt = new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi); + merge.setNext(graph.add(dynamicDeopt)); + } + List obsoletes = new LinkedList<>(); + obsoletes.add(first); + + do { + AbstractDeoptimizeNode deopt = iterator.next(); + EndNode newEnd = graph.add(new EndNode()); + merge.addForwardEnd(newEnd); + reasonActionPhi.addInput(deopt.getActionAndReason(context.getMetaAccess())); + speculationPhi.addInput(deopt.getSpeculation(context.getMetaAccess())); + deopt.replaceAtPredecessor(newEnd); + exitLoops(deopt, newEnd, cfg); + obsoletes.add(deopt); + } while (iterator.hasNext()); + + dynamicDeopt.setStateBefore(fs); + for (AbstractDeoptimizeNode obsolete : obsoletes) { + obsolete.safeDelete(); } } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java 2019-04-24 19:25:41.000000000 +0000 @@ -254,6 +254,8 @@ for (MemoryMap state : states) { MemoryNode last = state.getLastLocationAccess(key); if (isPhi) { + // Fortify: Suppress Null Deference false positive (`isPhi == true` implies + // `merged != null`) ((MemoryPhiNode) merged).addInput(ValueNodeUtil.asNode(last)); } else { if (merged == last) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java 2019-04-24 19:25:41.000000000 +0000 @@ -69,7 +69,7 @@ private FixedNodeRelativeFrequencyCache probabilites = new FixedNodeRelativeFrequencyCache(); public InlineableGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context, CanonicalizerPhase canonicalizer, boolean trackNodeSourcePosition) { - StructuredGraph original = InliningUtil.getIntrinsicGraph(context.getReplacements(), method, invoke.bci(), trackNodeSourcePosition, null); + StructuredGraph original = context.getReplacements().getSubstitution(method, invoke.bci(), trackNodeSourcePosition, null, invoke.asNode().getOptions()); if (original == null) { original = parseBytecodes(method, context, canonicalizer, invoke.asNode().graph(), trackNodeSourcePosition); } else if (original.isFrozen()) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java 2019-04-24 19:25:41.000000000 +0000 @@ -72,7 +72,6 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; -import org.graalvm.compiler.nodes.KillingBeginNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.MergeNode; import org.graalvm.compiler.nodes.NodeView; @@ -93,7 +92,6 @@ import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.MonitorExitNode; import org.graalvm.compiler.nodes.java.MonitorIdNode; -import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; @@ -466,11 +464,7 @@ // A partial intrinsic exit must be replaced with a call to // the intrinsified method. Invoke dup = (Invoke) duplicates.get(exit.asNode()); - if (dup instanceof InvokeNode) { - ((InvokeNode) dup).replaceWithNewBci(invoke.bci()); - } else { - ((InvokeWithExceptionNode) dup).replaceWithNewBci(invoke.bci()); - } + dup.replaceBci(invoke.bci()); } if (unwindNode != null) { unwindNode = (UnwindNode) duplicates.get(unwindNode); @@ -544,15 +538,7 @@ } // get rid of memory kill - AbstractBeginNode begin = invokeWithException.next(); - if (begin instanceof KillingBeginNode) { - try (DebugCloseable position = begin.withNodeSourcePosition()) { - AbstractBeginNode newBegin = new BeginNode(); - graph.addAfterFixed(begin, graph.add(newBegin)); - begin.replaceAtUsages(newBegin); - graph.removeFixed(begin); - } - } + invokeWithException.killKillingBegin(); } else { if (unwindNode != null && unwindNode.isAlive()) { try (DebugCloseable position = unwindNode.withNodeSourcePosition()) { @@ -836,7 +822,7 @@ // Return value does no longer need to be limited by the monitor exit. for (MonitorExitNode n : frameState.usages().filter(MonitorExitNode.class)) { - n.clearEscapedReturnValue(); + n.clearEscapedValue(); } frameState.replaceAndDelete(stateAfterReturn); @@ -1005,14 +991,6 @@ } } - public static boolean canIntrinsify(Replacements replacements, ResolvedJavaMethod target, int invokeBci) { - return replacements.hasSubstitution(target, invokeBci); - } - - public static StructuredGraph getIntrinsicGraph(Replacements replacements, ResolvedJavaMethod target, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { - return replacements.getSubstitution(target, invokeBci, trackNodeSourcePosition, replaceePosition); - } - /** * This method exclude InstrumentationNode from inlining heuristics. */ diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/AbstractInliningPolicy.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/AbstractInliningPolicy.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/AbstractInliningPolicy.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/AbstractInliningPolicy.java 2019-04-24 19:25:41.000000000 +0000 @@ -31,7 +31,6 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.Replacements; -import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable; @@ -69,7 +68,7 @@ private static boolean onlyIntrinsics(Replacements replacements, InlineInfo info) { for (int i = 0; i < info.numberOfMethods(); i++) { - if (!InliningUtil.canIntrinsify(replacements, info.methodAt(i), info.invoke().bci())) { + if (!replacements.hasSubstitution(info.methodAt(i), info.invoke().bci())) { return false; } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java 2019-04-24 19:25:41.000000000 +0000 @@ -64,10 +64,10 @@ } @Override - public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) { - final boolean isTracing = TraceInlining.getValue(replacements.getOptions()); + public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) { + OptionValues options = calleeInfo.graph().getOptions(); + final boolean isTracing = TraceInlining.getValue(options); final InlineInfo info = invocation.callee(); - OptionValues options = info.graph().getOptions(); final double probability = invocation.probability(); final double relevance = invocation.relevance(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java 2019-04-24 19:25:41.000000000 +0000 @@ -31,6 +31,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.phases.common.inlining.InliningUtil; +import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation; public class InlineEverythingPolicy implements InliningPolicy { @@ -44,7 +45,7 @@ } @Override - public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) { - return Decision.YES.withReason(GraalOptions.TraceInlining.getValue(replacements.getOptions()), "inline everything"); + public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) { + return Decision.YES.withReason(GraalOptions.TraceInlining.getValue(calleeInfo.graph().getOptions()), "inline everything"); } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java 2019-04-24 19:25:41.000000000 +0000 @@ -28,6 +28,7 @@ import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -38,11 +39,11 @@ public final class InlineMethodSubstitutionsPolicy extends InlineEverythingPolicy { @Override - public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) { - final boolean isTracing = GraalOptions.TraceInlining.getValue(replacements.getOptions()); + public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) { + final boolean isTracing = GraalOptions.TraceInlining.getValue(calleeInfo.graph().getOptions()); CallTargetNode callTarget = invocation.callee().invoke().callTarget(); if (callTarget instanceof MethodCallTargetNode) { - ResolvedJavaMethod calleeMethod = ((MethodCallTargetNode) callTarget).targetMethod(); + ResolvedJavaMethod calleeMethod = callTarget.targetMethod(); if (replacements.hasSubstitution(calleeMethod, invocation.callee().invoke().bci())) { return Decision.YES.withReason(isTracing, "has a method subtitution"); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java 2019-04-24 19:25:41.000000000 +0000 @@ -26,6 +26,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation; public interface InliningPolicy { @@ -60,5 +61,5 @@ boolean continueInlining(StructuredGraph graph); - Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed); + Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java 2019-04-24 19:25:41.000000000 +0000 @@ -45,6 +45,7 @@ import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CallTargetNode; +import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; @@ -144,7 +145,7 @@ OptionValues options = rootGraph.getOptions(); if (method == null) { return "the method is not resolved"; - } else if (method.isNative() && (!Intrinsify.getValue(options) || !InliningUtil.canIntrinsify(context.getReplacements(), method, invokeBci))) { + } else if (method.isNative() && (!Intrinsify.getValue(options) || !context.getReplacements().hasSubstitution(method, invokeBci))) { return "it is a non-intrinsic native method"; } else if (method.isAbstract()) { return "it is an abstract method"; @@ -191,11 +192,12 @@ MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); ResolvedJavaMethod targetMethod = callTarget.targetMethod(); - if (callTarget.invokeKind() == CallTargetNode.InvokeKind.Special || targetMethod.canBeStaticallyBound()) { + InvokeKind invokeKind = callTarget.invokeKind(); + if (invokeKind == CallTargetNode.InvokeKind.Special || invokeKind == CallTargetNode.InvokeKind.Static || targetMethod.canBeStaticallyBound()) { return getExactInlineInfo(invoke, targetMethod); } - assert callTarget.invokeKind().isIndirect(); + assert invokeKind.isIndirect(); ResolvedJavaType holder = targetMethod.getDeclaringClass(); if (!(callTarget.receiver().stamp(NodeView.DEFAULT) instanceof ObjectStamp)) { @@ -457,7 +459,7 @@ assert callerCallsiteHolder.containsInvoke(calleeInfo.invoke()); counterInliningConsidered.increment(debug); - InliningPolicy.Decision decision = inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, inliningDepth, true); + InliningPolicy.Decision decision = inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, calleeInfo, inliningDepth, true); if (decision.shouldInline()) { doInline(callerCallsiteHolder, calleeInvocation, decision.getReason()); return true; @@ -718,7 +720,8 @@ final MethodInvocation currentInvocation = currentInvocation(); - final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(context.getReplacements(), currentInvocation, inliningDepth(), false).shouldInline()); + final boolean backtrack = (!currentInvocation.isRoot() && + !inliningPolicy.isWorthInlining(context.getReplacements(), currentInvocation, currentInvocation.callee(), inliningDepth(), false).shouldInline()); if (backtrack) { int remainingGraphs = currentInvocation.totalGraphs() - currentInvocation.processedGraphs(); assert remainingGraphs > 0; diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java 2019-04-24 19:25:41.000000000 +0000 @@ -137,7 +137,8 @@ int index = 0; for (AbstractEndNode end : merge.cfgPredecessors().snapshot()) { ValueNode thisReason = reasons != null ? reasons.get(index) : reason; - ValueNode thisSpeculation = speculations != null ? speculations.get(index++) : speculation; + ValueNode thisSpeculation = speculations != null ? speculations.get(index) : speculation; + index++; if (!thisReason.isConstant() || !thisSpeculation.isConstant()) { continue; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java 2019-04-24 19:25:41.000000000 +0000 @@ -69,6 +69,7 @@ import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.graphio.GraphBlocks; import org.graalvm.graphio.GraphElements; +import org.graalvm.graphio.GraphLocations; import org.graalvm.graphio.GraphOutput; import org.graalvm.graphio.GraphStructure; import org.graalvm.graphio.GraphTypes; @@ -77,7 +78,6 @@ import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Signature; -import org.graalvm.graphio.GraphLocations; public class BinaryGraphPrinter implements GraphStructure, Edges>, @@ -528,7 +528,7 @@ public URI getURI() { String path = e.getFileName(); try { - return path == null ? null : new URI(null, null, path, null); + return new URI(null, null, path == null ? "(Unknown Source)" : path, null); } catch (URISyntaxException ex) { throw new IllegalArgumentException(ex); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -188,11 +188,11 @@ return locationIdentity; } - @NodeIntrinsic + @NodeIntrinsic(hasSideEffect = true) private static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter JavaKind elementKind, @ConstantNodeParameter boolean aligned, @ConstantNodeParameter boolean disjoint, @ConstantNodeParameter boolean uninitialized, @ConstantNodeParameter int heapWordSize); - @NodeIntrinsic + @NodeIntrinsic(hasSideEffect = true) private static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter JavaKind elementKind, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter boolean aligned, @ConstantNodeParameter boolean disjoint, @ConstantNodeParameter boolean uninitialized, @ConstantNodeParameter int heapWordSize); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java 2019-04-24 19:25:41.000000000 +0000 @@ -49,9 +49,10 @@ import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.RawLoadNode; +import org.graalvm.compiler.nodes.extended.GuardedUnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -69,7 +70,6 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; -import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.internal.vm.compiler.word.Pointer; @@ -108,19 +108,10 @@ protected abstract int heapWordSize(); - @Snippet - public void arraycopyZeroLengthSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, - @ConstantParameter Counters counters) { - Object nonNullSrc = GraalDirectives.guardingNonNull(src); - Object nonNullDest = GraalDirectives.guardingNonNull(dest); - this.checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); - counters.zeroLengthStaticCounter.inc(); - } - + @SuppressWarnings("unused") @Snippet public void arraycopyExactSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, - @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, + @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, @ConstantParameter SnippetCounter elementKindCounter, @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); @@ -130,31 +121,37 @@ elementKindCounter.inc(); elementKindCopiedCounter.add(length); - ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind, locationIdentity, heapWordSize()); + + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind); } + @SuppressWarnings("unused") @Snippet - public void arraycopyUnrolledSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, - @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, @ConstantParameter int unrolledLength, @ConstantParameter Counters counters) { + public void arraycopyExactStubCallSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, + @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, + @ConstantParameter SnippetCounter elementKindCounter, @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck); checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); incrementLengthCounter(length, counters); - unrolledArraycopyWork(nonNullSrc, srcPos, nonNullDest, destPos, unrolledLength, elementKind, locationIdentity); + elementKindCounter.inc(); + elementKindCopiedCounter.add(length); + + ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind, locationIdentity, heapWordSize()); } @Snippet - public void arraycopyCheckcastSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, - @ConstantParameter Counters counters, @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind) { + public void arraycopyCheckcastSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @ConstantParameter Counters counters, + @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck); checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); incrementLengthCounter(length, counters); - ArrayCopyWithSlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind); + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind); } @Snippet @@ -166,7 +163,7 @@ checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); incrementLengthCounter(length, counters); - ArrayCopyWithSlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind); + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind); } @Snippet @@ -179,31 +176,35 @@ System.arraycopy(src, srcPos, dest, destPos, length); } - private static void unrolledArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation) { + @SuppressWarnings("unused") + @Snippet(allowPartialIntrinsicArgumentMismatch = true) + public void exactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity arrayLocation, + @ConstantParameter Counters counters) { int scale = ReplacementsUtil.arrayIndexScale(INJECTED_META_ACCESS, elementKind); int arrayBaseOffset = ReplacementsUtil.getArrayBaseOffset(INJECTED_META_ACCESS, elementKind); - long sourceOffset = arrayBaseOffset + (long) srcPos * scale; long destOffset = arrayBaseOffset + (long) destPos * scale; - long position = 0; - long delta = scale; - if (probability(NOT_FREQUENT_PROBABILITY, nonNullSrc == nonNullDest && srcPos < destPos)) { - // bad aliased case so we need to copy the array from back to front - position = (long) (length - 1) * scale; - delta = -delta; - } - // the length was already checked before - we can emit unconditional instructions - ExplodeLoopNode.explodeLoop(); - for (int iteration = 0; iteration < length; iteration++) { - Object value = RawLoadNode.load(nonNullSrc, sourceOffset + position, elementKind, arrayLocation); - RawStoreNode.storeObject(nonNullDest, destOffset + position, value, elementKind, arrayLocation, false); - position += delta; + GuardingNode anchor = SnippetAnchorNode.anchor(); + if (probability(NOT_FREQUENT_PROBABILITY, src == dest && srcPos < destPos)) { + // bad aliased case so we need to copy the array from back to front + for (int position = length - 1; position >= 0; position--) { + Object value = GuardedUnsafeLoadNode.guardedLoad(src, sourceOffset + ((long) position) * scale, elementKind, arrayLocation, anchor); + RawStoreNode.storeObject(dest, destOffset + ((long) position) * scale, value, elementKind, arrayLocation, true); + } + } else { + for (int position = 0; position < length; position++) { + Object value = GuardedUnsafeLoadNode.guardedLoad(src, sourceOffset + ((long) position) * scale, elementKind, arrayLocation, anchor); + RawStoreNode.storeObject(dest, destOffset + ((long) position) * scale, value, elementKind, arrayLocation, true); + } } } + @SuppressWarnings("unused") @Snippet(allowPartialIntrinsicArgumentMismatch = true) - public void checkcastArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { + public void checkcastArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, + @ConstantParameter LocationIdentity arrayLocation, + @ConstantParameter Counters counters) { if (probability(FREQUENT_PROBABILITY, length > 0)) { Object nonNullSrc = PiNode.asNonNullObject(src); Object nonNullDest = PiNode.asNonNullObject(dest); @@ -234,8 +235,11 @@ } } + @SuppressWarnings("unused") @Snippet(allowPartialIntrinsicArgumentMismatch = true) - public void genericArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { + public void genericArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, + @ConstantParameter LocationIdentity arrayLocation, + @ConstantParameter Counters counters) { // The length > 0 check should not be placed here because generic array copy stub should // enforce type check. This is fine performance-wise because this snippet is rarely used. counters.genericArraycopyDifferentTypeCounter.inc(); @@ -352,16 +356,17 @@ public static class Templates extends SnippetTemplate.AbstractTemplates { private final SnippetInfo arraycopyGenericSnippet; - private final SnippetInfo arraycopyUnrolledSnippet; private final SnippetInfo arraycopyExactSnippet; - private final SnippetInfo arraycopyZeroLengthSnippet; + private final SnippetInfo arraycopyExactStubCallSnippet; private final SnippetInfo arraycopyCheckcastSnippet; private final SnippetInfo arraycopyNativeSnippet; private final SnippetInfo checkcastArraycopyWithSlowPathWork; private final SnippetInfo genericArraycopyWithSlowPathWork; + private final SnippetInfo exactArraycopyWithSlowPathWork; private ResolvedJavaMethod originalArraycopy; private final Counters counters; + private boolean expandArraycopyLoop; public Templates(ArrayCopySnippets receiver, OptionValues options, Iterable factories, Factory factory, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { @@ -369,13 +374,13 @@ this.counters = new Counters(factory); arraycopyGenericSnippet = snippet(receiver, "arraycopyGenericSnippet"); - arraycopyUnrolledSnippet = snippet(receiver, "arraycopyUnrolledSnippet"); arraycopyExactSnippet = snippet(receiver, "arraycopyExactSnippet"); - arraycopyZeroLengthSnippet = snippet(receiver, "arraycopyZeroLengthSnippet"); + arraycopyExactStubCallSnippet = snippet(receiver, "arraycopyExactStubCallSnippet"); arraycopyCheckcastSnippet = snippet(receiver, "arraycopyCheckcastSnippet"); arraycopyNativeSnippet = snippet(null, "arraycopyNativeSnippet"); checkcastArraycopyWithSlowPathWork = snippet(receiver, "checkcastArraycopyWithSlowPathWork"); genericArraycopyWithSlowPathWork = snippet(receiver, "genericArraycopyWithSlowPathWork"); + exactArraycopyWithSlowPathWork = snippet(receiver, "exactArraycopyWithSlowPathWork"); } protected SnippetInfo snippet(ArrayCopySnippets receiver, String methodName) { @@ -401,7 +406,7 @@ if (arraycopy.isExact()) { // there is a sufficient type match - we don't need any additional type checks - snippetInfo = arraycopyExactSnippet; + snippetInfo = arraycopyExactStubCallSnippet; arrayTypeCheck = ArrayCopyTypeCheck.NO_ARRAY_TYPE_CHECK; } else if (srcComponentType == null && destComponentType == null) { // we don't know anything about the types - use the generic copying @@ -426,7 +431,7 @@ if (nonNullComponentType.isPrimitive()) { // one involved object is a primitive array - it is sufficient to directly // compare the hub. - snippetInfo = arraycopyExactSnippet; + snippetInfo = arraycopyExactStubCallSnippet; arrayTypeCheck = ArrayCopyTypeCheck.HUB_BASED_ARRAY_TYPE_CHECK; elementKind = nonNullComponentType.getJavaKind(); } else { @@ -438,17 +443,8 @@ } } - // a few special cases that are easier to handle when all other variables already have a - // value - if (snippetInfo != arraycopyNativeSnippet && snippetInfo != arraycopyGenericSnippet && arraycopy.getLength().isConstant() && arraycopy.getLength().asJavaConstant().asLong() == 0) { - // Copying 0 element between object arrays with conflicting types will not throw an - // exception - once we pass the preliminary element type checks that we are not - // mixing arrays of different basic types, ArrayStoreException is only thrown when - // an *astore would have thrown it. Therefore, copying null between object arrays - // with conflicting types will also succeed (we do not optimize for such case here). - snippetInfo = arraycopyZeroLengthSnippet; - } else if (snippetInfo == arraycopyExactSnippet && shouldUnroll(arraycopy.getLength())) { - snippetInfo = arraycopyUnrolledSnippet; + if (this.expandArraycopyLoop && snippetInfo == arraycopyExactStubCallSnippet) { + snippetInfo = arraycopyExactSnippet; } // create the snippet @@ -463,13 +459,9 @@ args.addConst("arrayTypeCheck", arrayTypeCheck); } Object locationIdentity = arraycopy.killsAnyLocation() ? LocationIdentity.any() : NamedLocationIdentity.getArrayLocation(elementKind); - if (snippetInfo == arraycopyUnrolledSnippet) { - args.addConst("elementKind", elementKind != null ? elementKind : JavaKind.Illegal); - args.addConst("locationIdentity", locationIdentity); - args.addConst("unrolledLength", arraycopy.getLength().asJavaConstant().asInt()); - } - if (snippetInfo == arraycopyExactSnippet) { + if (snippetInfo == arraycopyExactStubCallSnippet || snippetInfo == arraycopyExactSnippet) { assert elementKind != null; + args.addConst("workSnippet", exactArraycopyWithSlowPathWork); args.addConst("elementKind", elementKind); args.addConst("locationIdentity", locationIdentity); args.addConst("elementKindCounter", counters.arraycopyCallCounters.get(elementKind)); @@ -488,11 +480,19 @@ instantiate(args, arraycopy); } - public void lower(ArrayCopyWithSlowPathNode arraycopy, LoweringTool tool) { + public void lower(ArrayCopyWithDelayedLoweringNode arraycopy, LoweringTool tool) { StructuredGraph graph = arraycopy.graph(); - if (!graph.getGuardsStage().areFrameStatesAtDeopts()) { - // if an arraycopy contains a slow path, we can't lower it right away - return; + + if (arraycopy.getSnippet() == exactArraycopyWithSlowPathWork && this.expandArraycopyLoop) { + if (!graph.getGuardsStage().areDeoptsFixed()) { + // Don't lower until floating guards are fixed. + return; + } + } else { + if (!graph.getGuardsStage().areFrameStatesAtDeopts()) { + // Don't lower until frame states are assigned to deoptimization points. + return; + } } SnippetInfo snippetInfo = arraycopy.getSnippet(); @@ -502,6 +502,12 @@ args.add("dest", arraycopy.getDestination()); args.add("destPos", arraycopy.getDestinationPosition()); args.add("length", arraycopy.getLength()); + + JavaKind elementKind = arraycopy.getElementKind(); + args.addConst("elementKind", (elementKind == null) ? JavaKind.Illegal : elementKind); + + Object locationIdentity = (elementKind == null) ? LocationIdentity.any() : NamedLocationIdentity.getArrayLocation(arraycopy.getElementKind()); + args.addConst("arrayLocation", locationIdentity); args.addConst("counters", counters); instantiate(args, arraycopy); } @@ -526,10 +532,6 @@ return srcType.getComponentType().getJavaKind(); } - private static boolean shouldUnroll(ValueNode length) { - return length.isConstant() && length.asJavaConstant().asInt() <= 8 && length.asJavaConstant().asInt() != 0; - } - /** * Instantiate the snippet template and fix up the FrameState of any Invokes of * System.arraycopy and propagate the captured bci in the ArrayCopySlowPathNode. @@ -551,19 +553,19 @@ throw new GraalError("unexpected invoke %s in snippet", call.targetMethod()); } // Here we need to fix the bci of the invoke - InvokeNode newInvoke = invoke.replaceWithNewBci(arraycopy.getBci()); - newInvoke.setStateDuring(null); - newInvoke.setStateAfter(null); + invoke.replaceBci(arraycopy.getBci()); + invoke.setStateDuring(null); + invoke.setStateAfter(null); if (arraycopy.stateDuring() != null) { - newInvoke.setStateDuring(arraycopy.stateDuring()); + invoke.setStateDuring(arraycopy.stateDuring()); } else { assert arraycopy.stateAfter() != null : arraycopy; - newInvoke.setStateAfter(arraycopy.stateAfter()); + invoke.setStateAfter(arraycopy.stateAfter()); } } else if (originalNode instanceof InvokeWithExceptionNode) { throw new GraalError("unexpected invoke with exception %s in snippet", originalNode); - } else if (originalNode instanceof ArrayCopyWithSlowPathNode) { - ArrayCopyWithSlowPathNode slowPath = (ArrayCopyWithSlowPathNode) replacements.get(originalNode); + } else if (originalNode instanceof ArrayCopyWithDelayedLoweringNode) { + ArrayCopyWithDelayedLoweringNode slowPath = (ArrayCopyWithDelayedLoweringNode) replacements.get(originalNode); assert arraycopy.stateAfter() != null : arraycopy; assert slowPath.stateAfter() == arraycopy.stateAfter(); slowPath.setBci(arraycopy.getBci()); @@ -582,5 +584,9 @@ } return originalArraycopy; } + + public void setExpandArraycopyLoop(boolean b) { + this.expandArraycopyLoop = b; + } } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.replacements.arraycopy; + +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.replacements.SnippetTemplate; +import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; + +import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.meta.JavaKind; + +@NodeInfo(allowedUsageTypes = InputType.Memory) +public final class ArrayCopyWithDelayedLoweringNode extends BasicArrayCopyNode { + + public static final NodeClass TYPE = NodeClass.create(ArrayCopyWithDelayedLoweringNode.class); + + private final SnippetTemplate.SnippetInfo snippet; + + public ArrayCopyWithDelayedLoweringNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, SnippetTemplate.SnippetInfo snippet, JavaKind elementKind) { + super(TYPE, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI); + assert StampTool.isPointerNonNull(src) && StampTool.isPointerNonNull(dest) : "must have been null checked"; + this.snippet = snippet; + } + + @NodeIntrinsic + public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter SnippetTemplate.SnippetInfo snippet, + @ConstantNodeParameter JavaKind elementKind); + + public SnippetTemplate.SnippetInfo getSnippet() { + return snippet; + } + + public void setBci(int bci) { + this.bci = bci; + } +} + diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithSlowPathNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithSlowPathNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithSlowPathNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithSlowPathNode.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -/* - * 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 - * 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. - */ - - -package org.graalvm.compiler.replacements.arraycopy; - -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.type.StampTool; -import org.graalvm.compiler.replacements.SnippetTemplate; -import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; - -import jdk.vm.ci.code.BytecodeFrame; -import jdk.vm.ci.meta.JavaKind; - -@NodeInfo(allowedUsageTypes = InputType.Memory) -public final class ArrayCopyWithSlowPathNode extends BasicArrayCopyNode { - - public static final NodeClass TYPE = NodeClass.create(ArrayCopyWithSlowPathNode.class); - - private final SnippetTemplate.SnippetInfo snippet; - - public ArrayCopyWithSlowPathNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, SnippetTemplate.SnippetInfo snippet, JavaKind elementKind) { - super(TYPE, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI); - assert StampTool.isPointerNonNull(src) && StampTool.isPointerNonNull(dest) : "must have been null checked"; - this.snippet = snippet; - } - - @NodeIntrinsic - public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter SnippetTemplate.SnippetInfo snippet, - @ConstantNodeParameter JavaKind elementKind); - - public SnippetTemplate.SnippetInfo getSnippet() { - return snippet; - } - - public void setBci(int bci) { - this.bci = bci; - } -} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java 2019-04-24 19:25:41.000000000 +0000 @@ -24,6 +24,8 @@ package org.graalvm.compiler.replacements; +import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; +import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import jdk.internal.vm.compiler.collections.EconomicMap; @@ -41,6 +43,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.phases.OptimisticOptimizations; @@ -82,45 +85,65 @@ } @SuppressWarnings("try") - private EncodedGraph createGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) { - // @formatter:off - StructuredGraph graphToEncode = new StructuredGraph.Builder(options, debug, allowAssumptions). - useProfilingInfo(false). - trackNodeSourcePosition(graphBuilderConfig.trackNodeSourcePosition()). - method(method). - setIsSubstitution(isSubstitution). - cancellable(graph.getCancellable()). - build(); + private EncodedGraph createGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) { + StructuredGraph graphToEncode; + if (isSubstitution && (UseEncodedGraphs.getValue(options) || IS_IN_NATIVE_IMAGE)) { + // These must go through Replacements to find the graph to use. + graphToEncode = providers.getReplacements().getMethodSubstitution(plugin, method, INLINE_AFTER_PARSING, allowAssumptions, + options); + } else { + graphToEncode = buildGraph(method, plugin, intrinsicBytecodeProvider, isSubstitution); + } + + /* + * ConvertDeoptimizeToGuardPhase reduces the number of merges in the graph, so that fewer + * frame states will be created. This significantly reduces the number of nodes in the + * initial graph. + */ + try (DebugContext.Scope scope = debug.scope("createGraph", graphToEncode)) { + PhaseContext context = new PhaseContext(providers); + new ConvertDeoptimizeToGuardPhase().apply(graphToEncode, context); + } catch (Throwable t) { + throw debug.handle(t); + } + + EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graphToEncode, architecture); + graphCache.put(method, encodedGraph); + return encodedGraph; + } + + @SuppressWarnings("try") + private StructuredGraph buildGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) { + StructuredGraph graphToEncode;// @formatter:off + graphToEncode = new StructuredGraph.Builder(options, debug, allowAssumptions). + useProfilingInfo(false). + trackNodeSourcePosition(graphBuilderConfig.trackNodeSourcePosition()). + method(plugin != null ? plugin.getSubstitute(providers.getMetaAccess()) : method). + setIsSubstitution(isSubstitution). + cancellable(graph.getCancellable()). + build(); // @formatter:on try (DebugContext.Scope scope = debug.scope("createGraph", graphToEncode)) { - IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null ? new IntrinsicContext(originalMethod, method, intrinsicBytecodeProvider, INLINE_AFTER_PARSING) : null; + IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null + ? new IntrinsicContext(method, plugin.getSubstitute(providers.getMetaAccess()), intrinsicBytecodeProvider, INLINE_AFTER_PARSING) : null; GraphBuilderPhase.Instance graphBuilderPhaseInstance = createGraphBuilderPhaseInstance(initialIntrinsicContext); graphBuilderPhaseInstance.apply(graphToEncode); PhaseContext context = new PhaseContext(providers); new CanonicalizerPhase().apply(graphToEncode, context); - /* - * ConvertDeoptimizeToGuardPhase reduces the number of merges in the graph, so that - * fewer frame states will be created. This significantly reduces the number of nodes in - * the initial graph. - */ - new ConvertDeoptimizeToGuardPhase().apply(graphToEncode, context); - - EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graphToEncode, architecture); - graphCache.put(method, encodedGraph); - return encodedGraph; } catch (Throwable ex) { throw debug.handle(ex); } + return graphToEncode; } @Override - protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, + protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, boolean trackNodeSourcePosition) { EncodedGraph result = graphCache.get(method); if (result == null && method.hasBytecodes()) { - result = createGraph(method, originalMethod, intrinsicBytecodeProvider, isSubstitution); + result = createGraph(method, plugin, intrinsicBytecodeProvider, isSubstitution); } return result; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java 2019-04-24 19:25:41.000000000 +0000 @@ -366,7 +366,7 @@ StructuredGraph calleeGraph; if (IS_IN_NATIVE_IMAGE) { - calleeGraph = providers.getReplacements().getSnippet(method, null, false, null); + calleeGraph = providers.getReplacements().getSnippet(method, null, null, false, null, invoke.getOptions()); } else { calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).trackNodeSourcePosition(invoke.graph().trackNodeSourcePosition()).setIsSubstitution( true).build(); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -281,6 +281,11 @@ } @Override + public boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, Receiver receiver, ValueNode[] argsIncludingReceiver) { + throw GraalError.shouldNotReachHere(); + } + + @Override public String toString() { return String.format("%s:intrinsic", method.format("%H.%n(%p)")); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,12 +46,16 @@ import jdk.vm.ci.meta.JavaKind; @NodeInfo(cycles = CYCLES_2, size = SIZE_1) -public final class BitCountNode extends UnaryNode implements ArithmeticLIRLowerable { +public class BitCountNode extends UnaryNode implements ArithmeticLIRLowerable { public static final NodeClass TYPE = NodeClass.create(BitCountNode.class); public BitCountNode(ValueNode value) { - super(TYPE, computeStamp(value.stamp(NodeView.DEFAULT), value), value); + this(TYPE, value); + } + + public BitCountNode(NodeClass c, ValueNode value) { + super(c, computeStamp(value.stamp(NodeView.DEFAULT), value), value); assert value.getStackKind() == JavaKind.Int || value.getStackKind() == JavaKind.Long; } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java 2019-04-24 19:25:41.000000000 +0000 @@ -95,6 +95,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind; +import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.nodes.java.LoadFieldNode; @@ -346,7 +347,7 @@ @Override public IntrinsicContext getIntrinsic() { - return null; + return PEGraphDecoder.this.getIntrinsic(); } @Override @@ -375,6 +376,11 @@ } @Override + public boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { + return false; + } + + @Override public void setStateAfter(StateSplit stateSplit) { throw unimplemented(); } @@ -422,6 +428,10 @@ } } + protected IntrinsicContext getIntrinsic() { + return null; + } + protected class PEAppendGraphBuilderContext extends PENonAppendGraphBuilderContext { protected FixedWithNextNode lastInstr; protected ValueNode pushedNode; @@ -523,6 +533,11 @@ appendInvoke(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData, callTarget); updateLastInstruction(invoke.asNode()); } + + @Override + public GraphBuilderContext getNonIntrinsicAncestor() { + return null; + } } @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) @@ -829,10 +844,10 @@ for (InlineInvokePlugin plugin : inlineInvokePlugins) { InlineInfo inlineInfo = plugin.shouldInlineInvoke(graphBuilderContext, targetMethod, arguments); if (inlineInfo != null) { - if (inlineInfo.getMethodToInline() == null) { - return null; - } else { + if (inlineInfo.allowsInlining()) { return doInline(methodScope, loopScope, invokeData, inlineInfo, arguments); + } else { + return null; } } } @@ -844,9 +859,7 @@ return null; } ResolvedJavaMethod inlineMethod = inlineInfo.getMethodToInline(); - ResolvedJavaMethod originalMethod = inlineInfo.getOriginalMethod(); - boolean isSubstitution = originalMethod != null && !originalMethod.equals(inlineMethod); - EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, originalMethod, inlineInfo.getIntrinsicBytecodeProvider(), isSubstitution, graph.trackNodeSourcePosition()); + EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, inlineInfo.getPlugin(), inlineInfo.getIntrinsicBytecodeProvider(), inlineInfo.isSubstitution(), graph.trackNodeSourcePosition()); if (graphToInline == null) { return null; } @@ -1115,7 +1128,7 @@ } } - protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, + protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, boolean trackNodeSourcePosition); @Override diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -27,9 +27,11 @@ import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static org.graalvm.compiler.core.common.GraalOptions.UseSnippetGraphCache; import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; +import static org.graalvm.compiler.debug.DebugOptions.DebugStubsAndSnippets; import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; import static org.graalvm.compiler.java.BytecodeParserOptions.InlineIntrinsicsDuringParsing; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; +import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createMethodSubstitutionInlineInfo; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; @@ -80,9 +82,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.spi.Replacements; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; @@ -99,15 +98,7 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin { - public static class Options { - // @formatter:off - @Option(help = "This is a testing option to exercise the SymbolicSnippetEncoder", type = OptionType.Expert) - public static final OptionKey UseEncodedSnippets = new OptionKey<>(false); - // @formatter:on - } - - protected final OptionValues options; - + @Override public Providers getProviders() { return providers; } @@ -122,11 +113,6 @@ private GraphBuilderConfiguration.Plugins graphBuilderPlugins; private final DebugHandlersFactory debugHandlersFactory; - @Override - public OptionValues getOptions() { - return options; - } - /** * The preprocessed replacement graphs. */ @@ -170,11 +156,11 @@ */ @Override public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - Bytecode subst = getSubstitutionBytecode(method); - if (subst != null) { + MethodSubstitutionPlugin msPlugin = getMethodSubstitution(method); + if (msPlugin != null) { if (b.parsingIntrinsic() || InlineDuringParsing.getValue(b.getOptions()) || InlineIntrinsicsDuringParsing.getValue(b.getOptions())) { // Forced inlining of intrinsics - return createIntrinsicInlineInfo(subst.getMethod(), method, subst.getOrigin()); + return createMethodSubstitutionInlineInfo(method, msPlugin); } return null; } @@ -182,7 +168,7 @@ assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded"; // Force inlining when parsing replacements - return createIntrinsicInlineInfo(method, null, defaultBytecodeProvider); + return createIntrinsicInlineInfo(method, defaultBytecodeProvider); } else { assert IS_BUILDING_NATIVE_IMAGE || method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(), @@ -215,9 +201,8 @@ // it is stable across VM executions (in support of replay compilation). private final EconomicMap snippetTemplateCache; - public ReplacementsImpl(OptionValues options, DebugHandlersFactory debugHandlersFactory, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, + public ReplacementsImpl(DebugHandlersFactory debugHandlersFactory, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { - this.options = options; this.providers = providers.copyWith(this); this.snippetReflection = snippetReflection; this.target = target; @@ -232,24 +217,28 @@ private static final AtomicInteger nextDebugContextId = new AtomicInteger(); - public DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) { - DebugContext outer = DebugContext.forCurrentThread(); - Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet()); - List factories = debugHandlersFactory == null ? Collections.emptyList() : Collections.singletonList(debugHandlersFactory); - return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, factories); + public DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method, OptionValues options) { + if (DebugStubsAndSnippets.getValue(options)) { + DebugContext outer = DebugContext.forCurrentThread(); + Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet()); + List factories = debugHandlersFactory == null ? Collections.emptyList() : Collections.singletonList(debugHandlersFactory); + return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, factories); + } + return DebugContext.disabled(options); } @Override @SuppressWarnings("try") - public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { + public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, + OptionValues options) { assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); assert method.hasBytecodes() : "Snippet must not be abstract or native"; StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(method) : null; if (graph == null || (trackNodeSourcePosition && !graph.trackNodeSourcePosition())) { - try (DebugContext debug = openDebugContext("Snippet_", method); + try (DebugContext debug = openDebugContext("Snippet_", method, options); DebugCloseable a = SnippetPreparationTime.start(debug)) { - StructuredGraph newGraph = makeGraph(debug, defaultBytecodeProvider, method, args, recursiveEntry, trackNodeSourcePosition, replaceePosition); + StructuredGraph newGraph = makeGraph(debug, defaultBytecodeProvider, method, args, recursiveEntry, trackNodeSourcePosition, replaceePosition, INLINE_AFTER_PARSING); DebugContext.counter("SnippetNodeCount[%#s]", method).add(newGraph.getDebug(), newGraph.getNodeCount()); if (!UseSnippetGraphCache.getValue(options) || args != null) { return newGraph; @@ -268,11 +257,23 @@ } @Override - public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { + public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { // No initialization needed as snippet graphs are created on demand in getSnippet } @Override + public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, + StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { + // Method substitutions are parsed by the BytecodeParser. + return null; + } + + @Override + public void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { + // No initialization needed as method substitutions are parsed by the BytecodeParser. + } + + @Override public boolean hasSubstitution(ResolvedJavaMethod method, int invokeBci) { InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method); return plugin != null && (!plugin.inlineOnly() || invokeBci >= 0); @@ -283,19 +284,17 @@ return defaultBytecodeProvider; } - @Override - public Bytecode getSubstitutionBytecode(ResolvedJavaMethod method) { + protected MethodSubstitutionPlugin getMethodSubstitution(ResolvedJavaMethod method) { InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method); if (plugin instanceof MethodSubstitutionPlugin) { MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; - ResolvedJavaMethod substitute = msPlugin.getSubstitute(providers.getMetaAccess()); - return msPlugin.getBytecodeProvider().getBytecode(substitute); + return msPlugin; } return null; } @Override - public StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { + public StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { StructuredGraph result; InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method); if (plugin != null && (!plugin.inlineOnly() || invokeBci >= 0)) { @@ -305,8 +304,8 @@ ResolvedJavaMethod substitute = msPlugin.getSubstitute(metaAccess); StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(substitute) : null; if (graph == null || graph.trackNodeSourcePosition() != trackNodeSourcePosition) { - try (DebugContext debug = openDebugContext("Substitution_", method)) { - graph = makeGraph(debug, msPlugin.getBytecodeProvider(), substitute, null, method, trackNodeSourcePosition, replaceePosition); + try (DebugContext debug = openDebugContext("Substitution_", method, options)) { + graph = makeGraph(debug, msPlugin.getBytecodeProvider(), substitute, null, method, trackNodeSourcePosition, replaceePosition, INLINE_AFTER_PARSING); if (!UseSnippetGraphCache.getValue(options)) { return graph; } @@ -319,7 +318,7 @@ result = graph; } else { Bytecode code = new ResolvedJavaMethodBytecode(method); - try (DebugContext debug = openDebugContext("Substitution_", method)) { + try (DebugContext debug = openDebugContext("Substitution_", method, options)) { result = new IntrinsicGraphBuilder(options, debug, providers, code, invokeBci).buildGraph(plugin); } } @@ -332,13 +331,13 @@ @SuppressWarnings("try") @Override public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug) { - Bytecode subst = getSubstitutionBytecode(method); - if (subst != null) { - ResolvedJavaMethod substMethod = subst.getMethod(); + MethodSubstitutionPlugin msPlugin = getMethodSubstitution(method); + if (msPlugin != null) { + ResolvedJavaMethod substMethod = msPlugin.getSubstitute(providers.getMetaAccess()); assert !substMethod.equals(method); - BytecodeProvider bytecodeProvider = subst.getOrigin(); + BytecodeProvider bytecodeProvider = msPlugin.getBytecodeProvider(); // @formatter:off - StructuredGraph graph = new StructuredGraph.Builder(options, debug, StructuredGraph.AllowAssumptions.YES). + StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug, StructuredGraph.AllowAssumptions.YES). method(substMethod). compilationId(compilationId). recordInlinedMethods(bytecodeProvider.shouldRecordMethodDependencies()). @@ -367,11 +366,32 @@ * @param args * @param original the original method if {@code method} is a {@linkplain MethodSubstitution * substitution} otherwise null - * @param trackNodeSourcePosition + * @param trackNodeSourcePosition record source information + * @param context + * {@link org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext + * compilation context} for the graph */ public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original, boolean trackNodeSourcePosition, - NodeSourcePosition replaceePosition) { - return createGraphMaker(method, original).makeGraph(debug, bytecodeProvider, args, trackNodeSourcePosition, replaceePosition); + NodeSourcePosition replaceePosition, IntrinsicContext.CompilationContext context) { + return createGraphMaker(method, original).makeGraph(debug, bytecodeProvider, args, trackNodeSourcePosition, replaceePosition, context); + } + + /** + * Creates a preprocessed graph for a snippet or method substitution with a context of . + * {@link org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext#INLINE_AFTER_PARSING} + * . + * + * + * @param bytecodeProvider how to access the bytecode of {@code method} + * @param method the snippet or method substitution for which a graph will be created + * @param args + * @param original the original method if {@code method} is a {@linkplain MethodSubstitution + * substitution} otherwise null + * @param trackNodeSourcePosition record source information + */ + public final StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original, + boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { + return makeGraph(debug, bytecodeProvider, method, args, original, trackNodeSourcePosition, replaceePosition, INLINE_AFTER_PARSING); } /** @@ -408,10 +428,11 @@ } @SuppressWarnings("try") - public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { + public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, + IntrinsicContext.CompilationContext context) { try (DebugContext.Scope s = debug.scope("BuildSnippetGraph", method)) { assert method.hasBytecodes() : method; - StructuredGraph graph = buildInitialGraph(debug, bytecodeProvider, method, args, trackNodeSourcePosition, replaceePosition); + StructuredGraph graph = buildInitialGraph(debug, bytecodeProvider, method, args, trackNodeSourcePosition, replaceePosition, context); finalizeGraph(graph); @@ -427,7 +448,7 @@ * Does final processing of a snippet graph. */ protected void finalizeGraph(StructuredGraph graph) { - if (!GraalOptions.SnippetCounters.getValue(replacements.options) || graph.getNodes().filter(SnippetCounterNode.class).isEmpty()) { + if (!GraalOptions.SnippetCounters.getValue(graph.getOptions()) || graph.getNodes().filter(SnippetCounterNode.class).isEmpty()) { int sideEffectCount = 0; assert (sideEffectCount = graph.getNodes().filter(e -> hasSideEffect(e)).count()) >= 0; new ConvertDeoptimizeToGuardPhase().apply(graph, null); @@ -471,16 +492,39 @@ return false; } + static class EncodedIntrinsicContext extends IntrinsicContext { + EncodedIntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, BytecodeProvider bytecodeProvider, CompilationContext compilationContext, + boolean allowPartialIntrinsicArgumentMismatch) { + super(method, intrinsic, bytecodeProvider, compilationContext, allowPartialIntrinsicArgumentMismatch); + } + + @Override + public boolean isDeferredInvoke(StateSplit stateSplit) { + if (stateSplit instanceof Invoke) { + Invoke invoke = (Invoke) stateSplit; + ResolvedJavaMethod method = invoke.callTarget().targetMethod(); + if (method.getAnnotation(Fold.class) != null) { + return true; + } + Node.NodeIntrinsic annotation = method.getAnnotation(Node.NodeIntrinsic.class); + if (annotation != null && !annotation.hasSideEffect()) { + return true; + } + } + return false; + } + } + /** * Builds the initial graph for a replacement. */ @SuppressWarnings("try") protected StructuredGraph buildInitialGraph(DebugContext debug, BytecodeProvider bytecodeProvider, final ResolvedJavaMethod methodToParse, Object[] args, boolean trackNodeSourcePosition, - NodeSourcePosition replaceePosition) { + NodeSourcePosition replaceePosition, IntrinsicContext.CompilationContext context) { // @formatter:off // Replacements cannot have optimistic assumptions since they have // to be valid for the entire run of the VM. - final StructuredGraph graph = new StructuredGraph.Builder(replacements.options, debug). + final StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug). method(methodToParse). trackNodeSourcePosition(trackNodeSourcePosition). callerContext(replaceePosition). @@ -506,11 +550,11 @@ MethodSubstitution methodAnnotation = method.getAnnotation(MethodSubstitution.class); if (methodAnnotation == null && snippetAnnotation == null) { // Post-parse inlined intrinsic - initialIntrinsicContext = new IntrinsicContext(substitutedMethod, method, bytecodeProvider, INLINE_AFTER_PARSING); + initialIntrinsicContext = new EncodedIntrinsicContext(substitutedMethod, method, bytecodeProvider, context, false); } else { // Snippet ResolvedJavaMethod original = substitutedMethod != null ? substitutedMethod : method; - initialIntrinsicContext = new IntrinsicContext(original, method, bytecodeProvider, INLINE_AFTER_PARSING, + initialIntrinsicContext = new EncodedIntrinsicContext(original, method, bytecodeProvider, context, snippetAnnotation != null ? snippetAnnotation.allowPartialIntrinsicArgumentMismatch() : true); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java 2019-04-24 19:25:41.000000000 +0000 @@ -675,7 +675,7 @@ ResolvedJavaMethod javaMethod = findMethod(providers.getMetaAccess(), declaringClass, methodName); assert javaMethod != null : "did not find @" + Snippet.class.getSimpleName() + " method in " + declaringClass + " named " + methodName; assert javaMethod.getAnnotation(Snippet.class) != null : javaMethod + " must be annotated with @" + Snippet.class.getSimpleName(); - providers.getReplacements().registerSnippet(javaMethod, original, receiver, GraalOptions.TrackNodeSourcePosition.getValue(options)); + providers.getReplacements().registerSnippet(javaMethod, original, receiver, GraalOptions.TrackNodeSourcePosition.getValue(options), options); LocationIdentity[] privateLocations = GraalOptions.SnippetCounters.getValue(options) ? SnippetCounterNode.addSnippetCounters(initialPrivateLocations) : initialPrivateLocations; if (GraalOptions.EagerSnippets.getValue(options)) { return new EagerSnippetInfo(javaMethod, original, privateLocations, receiver); @@ -691,7 +691,7 @@ Description description = new Description(args.cacheKey.method, "SnippetTemplate_" + nextSnippetTemplateId.incrementAndGet()); return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, factories); } - return DebugContext.DISABLED; + return DebugContext.disabled(options); } /** @@ -764,7 +764,8 @@ Object[] constantArgs = getConstantArgs(args); boolean shouldTrackNodeSourcePosition1 = trackNodeSourcePosition || (providers.getCodeCache() != null && providers.getCodeCache().shouldDebugNonSafepoints()); - StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method, args.info.original, constantArgs, shouldTrackNodeSourcePosition1, replacee.getNodeSourcePosition()); + StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method, args.info.original, constantArgs, shouldTrackNodeSourcePosition1, replacee.getNodeSourcePosition(), + options); ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); @@ -965,7 +966,9 @@ } retNode.setMemoryMap(null); } - memoryMap.safeDelete(); + if (memoryMap != null) { + memoryMap.safeDelete(); + } } if (needsAnchor) { snippetCopy.addAfterFixed(snippetCopy.start(), anchor); @@ -1484,55 +1487,6 @@ rewireFrameStates(replacee, duplicates); - if (replacee instanceof DeoptimizingNode) { - DeoptimizingNode replaceeDeopt = (DeoptimizingNode) replacee; - - FrameState stateBefore = null; - FrameState stateDuring = null; - FrameState stateAfter = null; - if (replaceeDeopt.canDeoptimize()) { - if (replaceeDeopt instanceof DeoptimizingNode.DeoptBefore) { - stateBefore = ((DeoptimizingNode.DeoptBefore) replaceeDeopt).stateBefore(); - } - if (replaceeDeopt instanceof DeoptimizingNode.DeoptDuring) { - stateDuring = ((DeoptimizingNode.DeoptDuring) replaceeDeopt).stateDuring(); - } - if (replaceeDeopt instanceof DeoptimizingNode.DeoptAfter) { - stateAfter = ((DeoptimizingNode.DeoptAfter) replaceeDeopt).stateAfter(); - } - } - - for (DeoptimizingNode deoptNode : deoptNodes) { - DeoptimizingNode deoptDup = (DeoptimizingNode) duplicates.get(deoptNode.asNode()); - if (deoptDup.canDeoptimize()) { - if (deoptDup instanceof DeoptimizingNode.DeoptBefore) { - ((DeoptimizingNode.DeoptBefore) deoptDup).setStateBefore(stateBefore); - } - if (deoptDup instanceof DeoptimizingNode.DeoptDuring) { - DeoptimizingNode.DeoptDuring deoptDupDuring = (DeoptimizingNode.DeoptDuring) deoptDup; - if (stateDuring != null) { - deoptDupDuring.setStateDuring(stateDuring); - } else if (stateAfter != null) { - deoptDupDuring.computeStateDuring(stateAfter); - } else if (stateBefore != null) { - assert !deoptDupDuring.hasSideEffect() : "can't use stateBefore as stateDuring for state split " + deoptDupDuring; - deoptDupDuring.setStateDuring(stateBefore); - } - } - if (deoptDup instanceof DeoptimizingNode.DeoptAfter) { - DeoptimizingNode.DeoptAfter deoptDupAfter = (DeoptimizingNode.DeoptAfter) deoptDup; - if (stateAfter != null) { - deoptDupAfter.setStateAfter(stateAfter); - } else { - assert !deoptDupAfter.hasSideEffect() : "can't use stateBefore as stateAfter for state split " + deoptDupAfter; - deoptDupAfter.setStateAfter(stateBefore); - } - - } - } - } - } - updateStamps(replacee, duplicates); rewireMemoryGraph(replacee, duplicates); @@ -1656,7 +1610,8 @@ FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); replaceeGraph.addAfterFixed(lastFixedNode, firstCFGNodeDuplicate); - rewireFrameStates(replacee, duplicates); + // floating nodes are not state-splits not need to re-wire frame states + assert !(replacee instanceof StateSplit); updateStamps(replacee, duplicates); rewireMemoryGraph(replacee, duplicates); @@ -1710,7 +1665,8 @@ } UnmodifiableEconomicMap duplicates = inlineSnippet(replacee, debug, replaceeGraph, replacements); - rewireFrameStates(replacee, duplicates); + // floating nodes are not state-splits not need to re-wire frame states + assert !(replacee instanceof StateSplit); updateStamps(replacee, duplicates); rewireMemoryGraph(replacee, duplicates); @@ -1725,12 +1681,64 @@ } protected void rewireFrameStates(ValueNode replacee, UnmodifiableEconomicMap duplicates) { - if (replacee instanceof StateSplit) { + if (replacee.graph().getGuardsStage().areFrameStatesAtSideEffects() && replacee instanceof StateSplit) { for (StateSplit sideEffectNode : sideEffectNodes) { assert ((StateSplit) replacee).hasSideEffect(); Node sideEffectDup = duplicates.get(sideEffectNode.asNode()); ((StateSplit) sideEffectDup).setStateAfter(((StateSplit) replacee).stateAfter()); } + } else if (replacee.graph().getGuardsStage().areFrameStatesAtDeopts() && replacee instanceof DeoptimizingNode) { + DeoptimizingNode replaceeDeopt = (DeoptimizingNode) replacee; + + FrameState stateBefore = null; + FrameState stateDuring = null; + FrameState stateAfter = null; + if (replaceeDeopt.canDeoptimize()) { + if (replaceeDeopt instanceof DeoptimizingNode.DeoptBefore) { + stateBefore = ((DeoptimizingNode.DeoptBefore) replaceeDeopt).stateBefore(); + } + if (replaceeDeopt instanceof DeoptimizingNode.DeoptDuring) { + stateDuring = ((DeoptimizingNode.DeoptDuring) replaceeDeopt).stateDuring(); + } + if (replaceeDeopt instanceof DeoptimizingNode.DeoptAfter) { + stateAfter = ((DeoptimizingNode.DeoptAfter) replaceeDeopt).stateAfter(); + } + } + + for (DeoptimizingNode deoptNode : deoptNodes) { + DeoptimizingNode deoptDup = (DeoptimizingNode) duplicates.get(deoptNode.asNode()); + if (deoptDup.canDeoptimize()) { + if (deoptDup instanceof DeoptimizingNode.DeoptBefore) { + ((DeoptimizingNode.DeoptBefore) deoptDup).setStateBefore(stateBefore); + } + if (deoptDup instanceof DeoptimizingNode.DeoptDuring) { + // compute a state "during" for a DeoptDuring inside the snippet depending + // on what kind of states we had on the node we are replacing. + // If the original node had a state "during" already, we just use that, + // otherwise we need to find a strategy to compute a state during based on + // some other state (before or after). + DeoptimizingNode.DeoptDuring deoptDupDuring = (DeoptimizingNode.DeoptDuring) deoptDup; + if (stateDuring != null) { + deoptDupDuring.setStateDuring(stateDuring); + } else if (stateAfter != null) { + deoptDupDuring.computeStateDuring(stateAfter); + } else if (stateBefore != null) { + assert !deoptDupDuring.hasSideEffect() : "can't use stateBefore as stateDuring for state split " + deoptDupDuring; + deoptDupDuring.setStateDuring(stateBefore); + } + } + if (deoptDup instanceof DeoptimizingNode.DeoptAfter) { + DeoptimizingNode.DeoptAfter deoptDupAfter = (DeoptimizingNode.DeoptAfter) deoptDup; + if (stateAfter != null) { + deoptDupAfter.setStateAfter(stateAfter); + } else { + assert !deoptDupAfter.hasSideEffect() : "can't use stateBefore as stateAfter for state split " + deoptDupAfter; + deoptDupAfter.setStateAfter(stateBefore); + } + + } + } + } } } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64BitCountNode.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64BitCountNode.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64BitCountNode.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64BitCountNode.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Arm Limited. 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. + */ + + +package org.graalvm.compiler.replacements.aarch64; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; + +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.replacements.nodes.BitCountNode; + +@NodeInfo(cycles = CYCLES_4, size = SIZE_4) +public final class AArch64BitCountNode extends BitCountNode { + + public static final NodeClass TYPE = NodeClass.create(AArch64BitCountNode.class); + + public AArch64BitCountNode(ValueNode value) { + super(TYPE, value); + } +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,8 +64,8 @@ invocationPlugins.defer(new Runnable() { @Override public void run() { - registerIntegerLongPlugins(invocationPlugins, AArch64IntegerSubstitutions.class, JavaKind.Int, bytecodeProvider); - registerIntegerLongPlugins(invocationPlugins, AArch64LongSubstitutions.class, JavaKind.Long, bytecodeProvider); + registerIntegerLongPlugins(invocationPlugins, JavaKind.Int, bytecodeProvider); + registerIntegerLongPlugins(invocationPlugins, JavaKind.Long, bytecodeProvider); if (registerMathPlugins) { registerMathPlugins(invocationPlugins); } @@ -80,7 +80,7 @@ }); } - private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class substituteDeclaringClass, JavaKind kind, BytecodeProvider bytecodeProvider) { + private static void registerIntegerLongPlugins(InvocationPlugins plugins, JavaKind kind, BytecodeProvider bytecodeProvider) { Class declaringClass = kind.toBoxedJavaClass(); Class type = kind.toJavaClass(); Registration r = new Registration(plugins, declaringClass, bytecodeProvider); @@ -108,7 +108,13 @@ return true; } }); - r.registerMethodSubstitution(substituteDeclaringClass, "bitCount", type); + r.register1("bitCount", type, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { + b.push(JavaKind.Int, b.append(new AArch64BitCountNode(value).canonical(null))); + return true; + } + }); } private static void registerMathPlugins(InvocationPlugins plugins) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerSubstitutions.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerSubstitutions.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerSubstitutions.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerSubstitutions.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2013, 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. - */ - - -package org.graalvm.compiler.replacements.aarch64; - -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; - -/** - * AArch64 ISA offers a count leading zeros instruction which can be used to implement - * numberOfLeadingZeros more efficiently than using BitScanReverse. - */ -@ClassSubstitution(Integer.class) -public class AArch64IntegerSubstitutions { - - @MethodSubstitution - public static int bitCount(int value) { - // Based on Warren, Hacker's Delight, slightly adapted to profit from Aarch64 add + shift - // instruction. - // Assuming the peephole optimizer optimizes all x - y >>> z into a single instruction - // this takes 10 instructions. - int x = value; - x = x - ((x & 0xaaaaaaaa) >>> 1); - x = (x & 0x33333333) + ((x & 0xcccccccc) >>> 2); - x = (x + (x >>> 4)) & 0x0f0f0f0f; - x = x + (x >>> 8); - x = x + (x >>> 16); - return x & 0x3f; - } -} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64LongSubstitutions.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64LongSubstitutions.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64LongSubstitutions.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64LongSubstitutions.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2013, 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. - */ - - -package org.graalvm.compiler.replacements.aarch64; - -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; - -/** - * Aarch64 ISA offers a count leading zeros instruction which can be used to implement - * numberOfLeadingZeros more efficiently than using BitScanReverse. - */ -@ClassSubstitution(Long.class) -public class AArch64LongSubstitutions { - - @MethodSubstitution - public static int bitCount(long value) { - // Based on Warren, Hacker's Delight, slightly adapted to profit from Aarch64 add + shift - // instruction. - // Assuming the peephole optimizer optimizes all x - y >>> z into a single instruction - // this takes 11 instructions. - long x = value; - x = x - ((x & 0xaaaaaaaaaaaaaaaaL) >>> 1); - x = (x & 0x3333333333333333L) + ((x & 0xccccccccccccccccL) >>> 2); - x = (x + (x >>> 4)) & 0x0f0f0f0f0f0f0f0fL; - x = x + (x >>> 8); - x = x + (x >>> 16); - x = x + (x >>> 32); - return (int) x & 0x7f; - } - -} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java 2019-04-24 19:25:41.000000000 +0000 @@ -84,7 +84,9 @@ if (processor.getAnnotation(param, processor.getType(INJECTED_PARAMETER_CLASS_NAME)) == null) { constantArgument(processor, out, deps, argCount, param.asType(), argCount); } else { - out.printf(" assert checkInjectedArgument(b, args[%d], targetMethod);\n", argCount); + out.printf(" if (!checkInjectedArgument(b, args[%d], targetMethod)) {\n", argCount); + out.printf(" return false;\n"); + out.printf(" }\n", argCount); out.printf(" %s arg%d = %s;\n", param.asType(), argCount, deps.use(processor, (DeclaredType) param.asType())); } argCount++; diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -140,6 +140,11 @@ return false; } + /** + * Keep test time down by only sampling a limited number of class files per jar. + */ + private static final int CLASSES_PER_JAR = 250; + @Test public void test() { RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class); @@ -156,28 +161,33 @@ if (shouldProcess(path)) { try { final ZipFile zipFile = new ZipFile(new File(path)); + int index = 0; + int step = zipFile.size() > CLASSES_PER_JAR ? zipFile.size() / CLASSES_PER_JAR : 1; for (final Enumeration entry = zipFile.entries(); entry.hasMoreElements();) { final ZipEntry zipEntry = entry.nextElement(); - String name = zipEntry.getName(); - if (name.endsWith(".class") && !name.equals("module-info.class") && !name.startsWith("META-INF/versions/")) { - String className = name.substring(0, name.length() - ".class".length()).replace('/', '.'); - if (isInNativeImage(className)) { - /* - * Native image requires non-graalsdk classes to be present in the - * classpath. - */ - continue; - } - if (isGSON(className)) { - /* uses old class format */ - continue; - } - try { - checkClass(metaAccess, getSnippetReflection(), className); - } catch (ClassNotFoundException e) { - throw new AssertionError(e); + if ((index % step) == 0) { + String name = zipEntry.getName(); + if (name.endsWith(".class") && !name.equals("module-info.class") && !name.startsWith("META-INF/versions/")) { + String className = name.substring(0, name.length() - ".class".length()).replace('/', '.'); + if (isInNativeImage(className)) { + /* + * Native image requires non-graalsdk classes to be present in + * the classpath. + */ + continue; + } + if (isGSON(className)) { + /* uses old class format */ + continue; + } + try { + checkClass(metaAccess, getSnippetReflection(), className); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } } } + index++; } } catch (IOException ex) { Assert.fail(ex.toString()); diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -116,7 +116,7 @@ StructuredGraph graph = testGraph(testMethodName); // Check to see if the resulting graph contains the expected node - StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null); + StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null, graph.getOptions()); if (replacement == null && !optional) { assertInGraph(graph, intrinsicClass); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -430,7 +430,7 @@ String compiledReturnValue = IN_COMPILED_HANDLER_MARKER; forceCompileOverride = true; inlineInvokeDecision = InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; - inlineInvokeMethodName = "stringizeId"; + inlineInvokeMethodName = "stringize"; try { testWithDifferentReturnValues(options, standardReturnValue, compiledReturnValue, "callStringize", THROW_EXCEPTION_MARKER); } finally { @@ -681,6 +681,11 @@ public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { return null; } + + @Override + public boolean isAvailable(ForeignCallDescriptor descriptor) { + return true; + } }; } if (type == SnippetReflectionProvider.class) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.replacements.test; + +import java.util.ArrayList; +import java.util.List; + +import jdk.internal.vm.compiler.collections.MapCursor; +import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.core.target.Backend; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; + +/** + * Exercise + * {@link org.graalvm.compiler.nodes.spi.Replacements#getIntrinsicGraph(ResolvedJavaMethod, CompilationIdentifier, DebugContext)} + * with regular method substitutions and encoded graphs. + */ +@RunWith(Parameterized.class) +public class RootMethodSubstitutionTest extends GraalCompilerTest { + + public RootMethodSubstitutionTest(ResolvedJavaMethod method) { + this.method = method; + } + + @Parameterized.Parameters(name = "{0}") + public static List data() { + ArrayList ret = new ArrayList<>(); + + Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); + Providers providers = backend.getProviders(); + + MapCursor> cursor = providers.getReplacements().getGraphBuilderPlugins().getInvocationPlugins().getBindings(true).getEntries(); + MetaAccessProvider metaAccess = providers.getMetaAccess(); + while (cursor.advance()) { + String className = cursor.getKey(); + ResolvedJavaType type = null; + try { + String typeName = className.substring(1, className.length() - 1).replace('/', '.'); + ClassLoader cl = ClassLoader.getSystemClassLoader(); + Class clazz = Class.forName(typeName, true, cl); + type = metaAccess.lookupJavaType(clazz); + } catch (ClassNotFoundException e) { + continue; + } + + for (InvocationPlugins.Binding binding : cursor.getValue()) { + if (binding.plugin instanceof MethodSubstitutionPlugin) { + ResolvedJavaMethod original = null; + for (ResolvedJavaMethod declared : type.getDeclaredMethods()) { + if (declared.getName().equals(binding.name)) { + if (declared.isStatic() == binding.isStatic) { + if (declared.getSignature().toMethodDescriptor().startsWith(binding.argumentsDescriptor)) { + original = declared; + break; + } + } + } + } + if (!original.isNative()) { + ret.add(new Object[]{original}); + } + } + } + } + return ret; + } + + private final ResolvedJavaMethod method; + + private StructuredGraph getIntrinsicGraph(boolean useEncodedGraphs) { + OptionValues options = new OptionValues(getDebugContext().getOptions(), GraalOptions.UseEncodedGraphs, useEncodedGraphs); + DebugContext debugContext = DebugContext.create(options, getDebugContext().getDescription(), getDebugHandlersFactories()); + return getReplacements().getIntrinsicGraph(method, CompilationIdentifier.INVALID_COMPILATION_ID, debugContext); + } + + StructuredGraph expectedGraph; + StructuredGraph actualGraph; + + @Override + protected boolean checkHighTierGraph(StructuredGraph graph) { + // Capture the graphs after high tier + if (expectedGraph == null) { + expectedGraph = (StructuredGraph) graph.copy(graph.getDebug()); + } else { + assert actualGraph == null; + actualGraph = (StructuredGraph) graph.copy(graph.getDebug()); + } + return super.checkHighTierGraph(graph); + } + + @Test + public void test() { + StructuredGraph regularGraph = getIntrinsicGraph(false); + assertTrue(regularGraph != null, "must produce a graph"); + getCode(method, regularGraph); + + StructuredGraph encodedGraph = getIntrinsicGraph(true); + assertTrue(encodedGraph != null, "must produce a graph"); + getCode(method, encodedGraph); + + // Compare the high tier graphs since the final graph might have scheduler + // differences because of different usage ordering. + assertEquals(expectedGraph, actualGraph, true, false); + } + +} diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -39,7 +39,7 @@ protected SnippetsTest() { ReplacementsImpl d = (ReplacementsImpl) getReplacements(); bytecodeProvider = getSystemClassLoaderBytecodeProvider(); - installer = new ReplacementsImpl(getInitialOptions(), null, d.getProviders(), d.snippetReflection, bytecodeProvider, d.target); + installer = new ReplacementsImpl(null, d.getProviders(), d.snippetReflection, bytecodeProvider, d.target); installer.setGraphBuilderPlugins(d.getGraphBuilderPlugins()); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -138,7 +138,7 @@ StructuredGraph graph = testGraph(testMethodName); // Check to see if the resulting graph contains the expected node - StructuredGraph replacement = getReplacements().getSubstitution(realJavaMethod, -1, false, null); + StructuredGraph replacement = getReplacements().getSubstitution(realJavaMethod, -1, false, null, graph.getOptions()); if (replacement == null && !optional) { assertInGraph(graph, intrinsicClass); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -83,7 +83,7 @@ StructuredGraph graph = testGraph(testMethod.getName()); // Check to see if the resulting graph contains the expected node - StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null); + StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null, graph.getOptions()); if (replacement == null) { assertInGraph(graph, expectedNode); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -312,7 +312,7 @@ } StructuredGraph replacementGraph() { - return getReplacements().getSubstitution(javamethod, -1, false, null); + return getReplacements().getSubstitution(javamethod, -1, false, null, getInitialOptions()); } StructuredGraph testMethodGraph() { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfCharTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfCharTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfCharTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfCharTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -53,8 +53,8 @@ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; String[] targets = new String[]{"foobar", "foo", "bar", "\u03bbfoobar", mediumString, mediumUTF16String, longString, longUTF16String}; int[] targetChars = new int[]{'f', 'o', 'r', 'x', Character.MIN_SUPPLEMENTARY_CODE_POINT}; - int[] targetOffsets = new int[18]; - for (int i = 0; i < 18; i++) { + int[] targetOffsets = new int[12]; + for (int i = 0; i < targetOffsets.length; i++) { targetOffsets[i] = i - 1; } for (String source : targets) { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -43,7 +43,7 @@ StructuredGraph graph = testGraph(testMethodName); // Check to see if the resulting graph contains the expected node - StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null); + StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null, graph.getOptions()); if (replacement == null && !optional) { assertInGraph(graph, intrinsicClass); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionTestBase.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionTestBase.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionTestBase.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionTestBase.java 2019-04-24 19:25:41.000000000 +0000 @@ -28,8 +28,8 @@ import org.junit.Assert; import org.junit.Assume; -import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -71,7 +71,7 @@ StructuredGraph graph = testGraph(testMethod.getName()); // Check to see if the resulting graph contains the expected node - StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null); + StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null, graph.getOptions()); if (replacement == null) { assertInGraph(graph, expectedNode); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -26,6 +26,7 @@ import static org.graalvm.compiler.core.GraalCompiler.compileGraph; import static org.graalvm.compiler.core.common.GraalOptions.TrackNodeSourcePosition; +import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; import java.util.List; @@ -44,6 +45,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; import org.junit.Assert; +import org.junit.Assume; import org.junit.Test; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -100,6 +102,7 @@ // at org.graalvm.compiler.replacements.test.SubstitutionNodeSourcePositionTest$TestMethod.test(int) [bci: -1] // at org.graalvm.compiler.replacements.test.SubstitutionNodeSourcePositionTest.methodSubstitution(SubstitutionNodeSourcePositionTest.java:89) [bci: 2] // @formatter:on + Assume.assumeFalse(UseEncodedGraphs.getValue(getInitialOptions())); checkMappings("methodSubstitution", true, TestMethod.class, "test"); } @@ -119,6 +122,7 @@ // // The precise snippet bytecodes don't matter, just ensure that some actually appear after // lowering. + Assume.assumeFalse(UseEncodedGraphs.getValue(getInitialOptions())); checkMappings("snippetLowering", true, SubstitutionNodeSourcePositionTest.class, "snippetLowering"); } diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java 2019-04-24 19:25:41.000000000 +0000 @@ -41,7 +41,7 @@ import jdk.vm.ci.services.Services; /** - * Interface to functionality that abstracts over which JDK version Graal is running on. + * JDK 9+ version of {@link GraalServices}. */ public final class GraalServices { diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -126,18 +126,14 @@ public boolean setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value, JavaKind theAccessKind, long offset) { ObjectState obj = state.getObjectState(virtual); assert obj.isVirtual() : "not virtual: " + obj; - ValueNode newValue; JavaKind entryKind = virtual.entryKind(index); JavaKind accessKind = theAccessKind != null ? theAccessKind : entryKind; - if (value == null) { - newValue = null; - } else { - newValue = closure.getAliasAndResolve(state, value); - } + ValueNode newValue = closure.getAliasAndResolve(state, value); getDebug().log(DebugContext.DETAILED_LEVEL, "Setting entry %d in virtual object %s %s results in %s", index, virtual.getObjectId(), virtual, state.getObjectState(virtual.getObjectId())); ValueNode oldValue = getEntry(virtual, index); boolean canVirtualize = entryKind == accessKind || (entryKind == accessKind.getStackKind() && virtual instanceof VirtualInstanceNode); if (!canVirtualize) { + assert entryKind != JavaKind.Long || newValue != null; if (entryKind == JavaKind.Long && oldValue.getStackKind() == newValue.getStackKind() && oldValue.getStackKind().isPrimitive()) { /* * Special case: If the entryKind is long, allow arbitrary kinds as long as a value diff -Nru openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java --- openjdk-13-13~17/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java 2019-04-24 19:25:41.000000000 +0000 @@ -634,7 +634,7 @@ switch (type) { case POOL_FIELD: { ResolvedJavaField field = (ResolvedJavaField) found[0]; - Objects.nonNull(field); + Objects.requireNonNull(field); writePoolObject(findFieldDeclaringClass(field)); writePoolObject(findFieldName(field)); writePoolObject(findFieldTypeName(field)); @@ -653,7 +653,7 @@ } case POOL_NODE_SOURCE_POSITION: { NodeSourcePosition pos = (NodeSourcePosition) found[0]; - Objects.nonNull(pos); + Objects.requireNonNull(pos); ResolvedJavaMethod method = findNodeSourcePositionMethod(pos); writePoolObject(method); final int bci = findNodeSourcePositionBCI(pos); @@ -697,7 +697,7 @@ } case POOL_NODE: { Node node = (Node) found[0]; - Objects.nonNull(node); + Objects.requireNonNull(node); writeInt(findNodeId(node)); writePoolObject(classForNode(node)); break; @@ -719,7 +719,7 @@ } case POOL_CLASS: { String typeName = (String) found[0]; - Objects.nonNull(typeName); + Objects.requireNonNull(typeName); writeString(typeName); String[] enumValueNames = findEnumTypeValues(object); if (enumValueNames != null) { @@ -735,7 +735,7 @@ } case POOL_METHOD: { ResolvedJavaMethod method = (ResolvedJavaMethod) found[0]; - Objects.nonNull(method); + Objects.requireNonNull(method); writePoolObject(findMethodDeclaringClass(method)); writePoolObject(findMethodName(method)); final Signature methodSignature = findMethodSignature(method); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -40,12 +40,16 @@ import javax.lang.model.util.SimpleTypeVisitor9; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; -import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.*; +import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.EXECUTABLE_MEMBER_PARAM; +import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER; +import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER_TYPE_PARAMS; +import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.RECEIVER_TYPE; /** * Print method and constructor info. @@ -79,7 +83,7 @@ Content typeParameters = getTypeParameters(member); if (!typeParameters.isEmpty()) { htmltree.add(typeParameters); - htmltree.add(Contents.SPACE); + htmltree.add(Entity.NO_BREAK_SPACE); } } @@ -107,7 +111,7 @@ } String signature = utils.flatSignature((ExecutableElement) member); if (signature.length() > 2) { - deprecatedLinkContent.add(Contents.ZERO_WIDTH_SPACE); + deprecatedLinkContent.add(Entity.ZERO_WIDTH_SPACE); } deprecatedLinkContent.add(signature); @@ -160,7 +164,7 @@ param.asType()).varargs(isVarArg)); tree.add(link); if(name(param).length() > 0) { - tree.add(Contents.SPACE); + tree.add(Entity.NO_BREAK_SPACE); tree.add(name(param)); } } @@ -176,11 +180,11 @@ protected void addReceiverAnnotations(ExecutableElement member, TypeMirror rcvrType, List annotationMirrors, Content tree) { writer.addReceiverAnnotationInfo(member, rcvrType, annotationMirrors, tree); - tree.add(Contents.SPACE); + tree.add(Entity.NO_BREAK_SPACE); tree.add(utils.getTypeName(rcvrType, false)); LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, RECEIVER_TYPE, rcvrType); tree.add(writer.getTypeParameterLinks(linkInfo)); - tree.add(Contents.SPACE); + tree.add(Entity.NO_BREAK_SPACE); tree.add("this"); } @@ -254,7 +258,7 @@ if (paramTree.isEmpty()) { htmltree.add("()"); } else { - htmltree.add(Contents.ZERO_WIDTH_SPACE); + htmltree.add(Entity.ZERO_WIDTH_SPACE); htmltree.add("("); htmltree.add(paramTree); paramTree.add(")"); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,9 +25,13 @@ package jdk.javadoc.internal.doclets.formats.html; -import java.io.*; -import java.util.*; -import java.util.zip.*; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.util.Collection; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; @@ -37,6 +41,7 @@ import javax.lang.model.util.SimpleElementVisitor9; import com.sun.source.doctree.DocTree; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -338,7 +343,7 @@ dlTree.add(dt); Content dd = new HtmlTree(HtmlTag.DD); if (sii.getDescription().isEmpty()) { - dd.add(Contents.SPACE); + dd.add(Entity.NO_BREAK_SPACE); } else { dd.add(sii.getDescription()); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,10 +25,10 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; import java.util.stream.Collectors; import javax.lang.model.element.Element; @@ -39,18 +39,26 @@ import javax.lang.model.type.TypeMirror; import com.sun.source.doctree.DocTree; + import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.Links; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.Resources; import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet; import jdk.javadoc.internal.doclets.toolkit.util.Utils; -import static javax.lang.model.element.Modifier.*; +import static javax.lang.model.element.Modifier.ABSTRACT; +import static javax.lang.model.element.Modifier.NATIVE; +import static javax.lang.model.element.Modifier.PUBLIC; +import static javax.lang.model.element.Modifier.STRICTFP; +import static javax.lang.model.element.Modifier.SYNCHRONIZED; /** * The base class for member writers. @@ -256,7 +264,7 @@ if (!set.isEmpty()) { String mods = set.stream().map(Modifier::toString).collect(Collectors.joining(" ")); htmltree.add(mods); - htmltree.add(Contents.SPACE); + htmltree.add(Entity.NO_BREAK_SPACE); } } @@ -284,7 +292,7 @@ addModifier(member, code); if (type == null) { code.add(utils.isClass(member) ? "class" : "interface"); - code.add(Contents.SPACE); + code.add(Entity.NO_BREAK_SPACE); } else { List list = utils.isExecutableElement(member) ? ((ExecutableElement)member).getTypeParameters() @@ -297,7 +305,7 @@ if (typeParameters.charCount() > 10) { code.add(new HtmlTree(HtmlTag.BR)); } else { - code.add(Contents.SPACE); + code.add(Entity.NO_BREAK_SPACE); } code.add( writer.getLink(new LinkInfoImpl(configuration, @@ -498,7 +506,7 @@ */ @Override public Content getInheritedSummaryHeader(TypeElement tElement) { - Content inheritedTree = writer.getMemberTreeHeader(); + Content inheritedTree = writer.getMemberInheritedTree(); writer.addInheritedSummaryHeader(this, tElement, inheritedTree); return inheritedTree; } @@ -551,8 +559,8 @@ */ public Content getMemberTree(Content memberTree, boolean isLastContent) { if (isLastContent) - return HtmlTree.UL(HtmlStyle.blockListLast, memberTree); + return HtmlTree.LI(HtmlStyle.blockListLast, memberTree); else - return HtmlTree.UL(HtmlStyle.blockList, memberTree); + return HtmlTree.LI(HtmlStyle.blockList, memberTree); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -118,7 +118,7 @@ Content headingContent = contents.getContent(heading); Content sectionHeading = HtmlTree.HEADING(Headings.CONTENT_HEADING, true, headingContent); - HtmlTree htmlTree = HtmlTree.SECTION(sectionHeading); + HtmlTree htmlTree = HtmlTree.SECTION(HtmlStyle.hierarchy, sectionHeading); addLevelInfo(!utils.isInterface(firstTypeElement) ? firstTypeElement : null, sset, isEnums, htmlTree); div.add(htmlTree); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -152,11 +152,8 @@ Content headerDiv = HtmlTree.DIV(HtmlStyle.header, pHeading); content.add(headerDiv); if (!table.isEmpty()) { - HtmlTree li = HtmlTree.LI(HtmlStyle.blockList, table.toContent()); - HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); - HtmlTree div = new HtmlTree(HtmlTag.DIV); + HtmlTree div = new HtmlTree(HtmlTag.DIV, table.toContent()); div.setStyle(HtmlStyle.allClassesContainer); - div.add(ul); content.add(div); if (table.needsScript()) { getMainBodyScript().append(table.getScript()); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -125,7 +125,6 @@ table.addRow(pkg, packageLinkContent, summaryContent); } } - HtmlTree li = HtmlTree.LI(HtmlStyle.blockList, table.toContent()); - content.add(HtmlTree.UL(HtmlStyle.blockList, li)); + content.add(table.toContent()); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,18 +25,19 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; - import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; @@ -72,7 +73,7 @@ Content memberSummaryTree) { memberSummaryTree.add( MarkerComments.START_OF_ANNOTATION_TYPE_FIELD_SUMMARY); - Content memberTree = writer.getMemberTreeHeader(); + Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, typeElement, memberTree); return memberTree; } @@ -88,7 +89,7 @@ * {@inheritDoc} */ public void addMemberTree(Content memberSummaryTree, Content memberTree) { - writer.addMemberTree(memberSummaryTree, memberTree); + writer.addMemberTree(HtmlStyle.fieldSummary, memberSummaryTree, memberTree); } /** @@ -101,16 +102,17 @@ /** * {@inheritDoc} */ - public void addAnnotationDetailsTreeHeader(TypeElement typeElement, - Content memberDetailsTree) { + public Content getAnnotationDetailsTreeHeader(TypeElement typeElement) { + Content memberDetailsTree = new ContentBuilder(); if (!writer.printedAnnotationFieldHeading) { - memberDetailsTree.add(links.createAnchor( - SectionName.ANNOTATION_TYPE_FIELD_DETAIL)); Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.fieldDetailsLabel); memberDetailsTree.add(heading); + memberDetailsTree.add(links.createAnchor( + SectionName.ANNOTATION_TYPE_FIELD_DETAIL)); writer.printedAnnotationFieldHeading = true; } + return memberDetailsTree; } /** @@ -118,12 +120,12 @@ */ public Content getAnnotationDocTreeHeader(Element member, Content annotationDetailsTree) { - annotationDetailsTree.add(links.createAnchor(name(member))); - Content annotationDocTree = writer.getMemberTreeHeader(); + Content annotationDocTree = new ContentBuilder(); Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING); heading.add(name(member)); annotationDocTree.add(heading); - return annotationDocTree; + annotationDocTree.add(links.createAnchor(name(member))); + return HtmlTree.SECTION(HtmlStyle.detail, annotationDocTree); } /** @@ -137,7 +139,7 @@ writer.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, getType(member))); pre.add(link); - pre.add(Contents.SPACE); + pre.add(Entity.NO_BREAK_SPACE); if (configuration.linksource) { Content memberName = new StringContent(name(member)); writer.addSrcLink(member, memberName, pre); @@ -171,8 +173,11 @@ /** * {@inheritDoc} */ - public Content getAnnotationDetails(Content annotationDetailsTree) { - return HtmlTree.SECTION(getMemberTree(annotationDetailsTree)); + public Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree) { + Content annotationDetails = new ContentBuilder(); + annotationDetails.add(annotationDetailsTreeHeader); + annotationDetails.add(annotationDetailsTree); + return getMemberTree(HtmlTree.SECTION(HtmlStyle.fieldDetails, annotationDetails)); } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,14 +25,14 @@ package jdk.javadoc.internal.doclets.formats.html; - -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter; @@ -74,7 +74,7 @@ Content memberSummaryTree) { memberSummaryTree.add( MarkerComments.START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY); - Content memberTree = writer.getMemberTreeHeader(); + Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, typeElement, memberTree); return memberTree; } @@ -84,7 +84,7 @@ */ @Override public void addMemberTree(Content memberSummaryTree, Content memberTree) { - writer.addMemberTree(memberSummaryTree, memberTree); + writer.addMemberTree(HtmlStyle.memberSummary, memberSummaryTree, memberTree); } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,18 +25,19 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; - import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; @@ -74,7 +75,7 @@ Content memberSummaryTree) { memberSummaryTree.add( MarkerComments.START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY); - Content memberTree = writer.getMemberTreeHeader(); + Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, typeElement, memberTree); return memberTree; } @@ -90,7 +91,7 @@ * {@inheritDoc} */ public void addMemberTree(Content memberSummaryTree, Content memberTree) { - writer.addMemberTree(memberSummaryTree, memberTree); + writer.addMemberTree(HtmlStyle.memberSummary, memberSummaryTree, memberTree); } /** @@ -103,16 +104,17 @@ /** * {@inheritDoc} */ - public void addAnnotationDetailsTreeHeader(TypeElement te, - Content memberDetailsTree) { + public Content getAnnotationDetailsTreeHeader(TypeElement te) { + Content memberDetailsTree = new ContentBuilder(); if (!writer.printedAnnotationHeading) { - memberDetailsTree.add(links.createAnchor( - SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL)); Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.annotationTypeDetailsLabel); memberDetailsTree.add(heading); + memberDetailsTree.add(links.createAnchor( + SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL)); writer.printedAnnotationHeading = true; } + return memberDetailsTree; } /** @@ -121,13 +123,13 @@ @Override public Content getAnnotationDocTreeHeader(Element member, Content annotationDetailsTree) { String simpleName = name(member); - annotationDetailsTree.add(links.createAnchor( - simpleName + utils.signature((ExecutableElement) member))); - Content annotationDocTree = writer.getMemberTreeHeader(); + Content annotationDocTree = new ContentBuilder(); Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING); heading.add(simpleName); annotationDocTree.add(heading); - return annotationDocTree; + annotationDocTree.add(links.createAnchor( + simpleName + utils.signature((ExecutableElement) member))); + return HtmlTree.SECTION(HtmlStyle.detail, annotationDocTree); } /** @@ -141,7 +143,7 @@ writer.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, getType(member))); pre.add(link); - pre.add(Contents.SPACE); + pre.add(Entity.NO_BREAK_SPACE); if (configuration.linksource) { Content memberName = new StringContent(name(member)); writer.addSrcLink(member, memberName, pre); @@ -175,8 +177,9 @@ /** * {@inheritDoc} */ - public Content getAnnotationDetails(Content annotationDetailsTree) { - return HtmlTree.SECTION(getMemberTree(annotationDetailsTree)); + public Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree) { + Content annotationDetails = new ContentBuilder(annotationDetailsTreeHeader, annotationDetailsTree); + return getMemberTree(HtmlTree.SECTION(HtmlStyle.memberDetails, annotationDetails)); } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -32,6 +32,7 @@ import javax.lang.model.element.TypeElement; import com.sun.source.doctree.DocTree; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -101,7 +102,7 @@ ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(annotationType); Content typeModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel); Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, typeModuleLabel); - moduleNameDiv.add(Contents.SPACE); + moduleNameDiv.add(Entity.NO_BREAK_SPACE); moduleNameDiv.add(getModuleLink(mdle, new StringContent(mdle.getQualifiedName()))); div.add(moduleNameDiv); } @@ -109,7 +110,7 @@ if (!pkg.isUnnamed()) { Content typePackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInType, contents.packageLabel); Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, typePackageLabel); - pkgNameDiv.add(Contents.SPACE); + pkgNameDiv.add(Entity.NO_BREAK_SPACE); Content pkgNameContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))); pkgNameDiv.add(pkgNameContent); div.add(pkgNameDiv); @@ -171,7 +172,7 @@ */ @Override public Content getAnnotationInfo(Content annotationInfoTree) { - return getMemberTree(HtmlStyle.description, annotationInfoTree); + return HtmlTree.SECTION(HtmlStyle.description, annotationInfoTree); } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -249,14 +249,13 @@ * @param contentTree the content tree to which the class use information will be added */ protected void addClassUse(Content contentTree) { - HtmlTree ul = new HtmlTree(HtmlTag.UL); - ul.setStyle(HtmlStyle.blockList); + Content content = new ContentBuilder(); if (configuration.packages.size() > 1) { - addPackageList(ul); - addPackageAnnotationList(ul); + addPackageList(content); + addPackageAnnotationList(content); } - addClassList(ul); - contentTree.add(ul); + addClassList(content); + contentTree.add(content); } /** @@ -276,8 +275,7 @@ for (PackageElement pkg : pkgSet) { addPackageUse(pkg, table); } - Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent()); - contentTree.add(li); + contentTree.add(table.toContent()); } /** @@ -305,8 +303,7 @@ addSummaryComment(pkg, summary); table.addRow(getPackageLink(pkg), summary); } - Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent()); - contentTree.add(li); + contentTree.add(table.toContent()); } /** @@ -319,7 +316,7 @@ ul.setStyle(HtmlStyle.blockList); for (PackageElement pkg : pkgSet) { Content markerAnchor = links.createAnchor(getPackageAnchorName(pkg)); - HtmlTree htmlTree = HtmlTree.SECTION(markerAnchor); + HtmlTree htmlTree = HtmlTree.SECTION(HtmlStyle.detail, markerAnchor); Content link = contents.getContent("doclet.ClassUse_Uses.of.0.in.1", getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)), @@ -329,7 +326,7 @@ addClassUse(pkg, htmlTree); ul.add(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); } - Content li = HtmlTree.LI(HtmlStyle.blockList, ul); + Content li = HtmlTree.SECTION(HtmlStyle.classUses, ul); contentTree.add(li); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,7 +25,11 @@ package jdk.javadoc.internal.doclets.formats.html; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; @@ -36,6 +40,7 @@ import javax.lang.model.util.SimpleElementVisitor8; import com.sun.source.doctree.DocTree; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -122,7 +127,7 @@ ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement); Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel); Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel); - moduleNameDiv.add(Contents.SPACE); + moduleNameDiv.add(Entity.NO_BREAK_SPACE); moduleNameDiv.add(getModuleLink(mdle, new StringContent(mdle.getQualifiedName()))); div.add(moduleNameDiv); @@ -131,7 +136,7 @@ if (!pkg.isUnnamed()) { Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInType, contents.packageLabel); Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel); - pkgNameDiv.add(Contents.SPACE); + pkgNameDiv.add(Entity.NO_BREAK_SPACE); Content pkgNameContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))); pkgNameDiv.add(pkgNameContent); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,10 +25,8 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - -import java.util.*; +import java.util.Collection; +import java.util.Set; import javax.lang.model.element.Modifier; import javax.lang.model.element.PackageElement; @@ -36,12 +34,15 @@ import javax.lang.model.element.VariableElement; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; @@ -157,7 +158,7 @@ Content headingContent = contents.contentsHeading; Content heading = HtmlTree.HEADING(Headings.CONTENT_HEADING, true, headingContent); - HtmlTree section = HtmlTree.SECTION(heading); + HtmlTree section = HtmlTree.SECTION(HtmlStyle.packages, heading); section.add(contentListTree); div.add(section); mainTree.add(div); @@ -194,7 +195,7 @@ Content heading = HtmlTree.HEADING(Headings.ConstantsSummary.PACKAGE_HEADING, true, pkgNameContent); heading.add(headingContent); - summaryTree = HtmlTree.SECTION(heading); + summaryTree = HtmlTree.SECTION(HtmlStyle.constantsSummary, heading); } /** @@ -265,7 +266,7 @@ for (Modifier mod : member.getModifiers()) { Content modifier = new StringContent(mod.toString()); code.add(modifier); - code.add(Contents.SPACE); + code.add(Entity.NO_BREAK_SPACE); } Content type = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CONSTANT_SUMMARY, member.asType())); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,25 +25,27 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - -import java.util.*; +import java.util.Arrays; +import java.util.List; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable; -import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*; +import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.CONSTRUCTORS; /** @@ -98,7 +100,7 @@ public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { memberSummaryTree.add(MarkerComments.START_OF_CONSTRUCTOR_SUMMARY); - Content memberTree = writer.getMemberTreeHeader(); + Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, typeElement, memberTree); return memberTree; } @@ -108,7 +110,7 @@ */ @Override public void addMemberTree(Content memberSummaryTree, Content memberTree) { - writer.addMemberTree(memberSummaryTree, memberTree); + writer.addMemberTree(HtmlStyle.constructorSummary, memberSummaryTree, memberTree); } /** @@ -118,12 +120,12 @@ public Content getConstructorDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) { memberDetailsTree.add(MarkerComments.START_OF_CONSTRUCTOR_DETAILS); - Content constructorDetailsTree = writer.getMemberTreeHeader(); - constructorDetailsTree.add(links.createAnchor( - SectionName.CONSTRUCTOR_DETAIL)); + Content constructorDetailsTree = new ContentBuilder(); Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.constructorDetailsLabel); constructorDetailsTree.add(heading); + constructorDetailsTree.add(links.createAnchor( + SectionName.CONSTRUCTOR_DETAIL)); return constructorDetailsTree; } @@ -134,15 +136,15 @@ public Content getConstructorDocTreeHeader(ExecutableElement constructor, Content constructorDetailsTree) { String erasureAnchor; - if ((erasureAnchor = getErasureAnchor(constructor)) != null) { - constructorDetailsTree.add(links.createAnchor((erasureAnchor))); - } - constructorDetailsTree.add(links.createAnchor(writer.getAnchor(constructor))); - Content constructorDocTree = writer.getMemberTreeHeader(); + Content constructorDocTree = new ContentBuilder(); Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING); heading.add(name(constructor)); constructorDocTree.add(heading); - return constructorDocTree; + if ((erasureAnchor = getErasureAnchor(constructor)) != null) { + constructorDocTree.add(links.createAnchor((erasureAnchor))); + } + constructorDocTree.add(links.createAnchor(writer.getAnchor(constructor))); + return HtmlTree.SECTION(HtmlStyle.detail, constructorDocTree); } /** @@ -194,8 +196,9 @@ * {@inheritDoc} */ @Override - public Content getConstructorDetails(Content constructorDetailsTree) { - return HtmlTree.SECTION(getMemberTree(constructorDetailsTree)); + public Content getConstructorDetails(Content constructorDetailsTreeHeader, Content constructorDetailsTree) { + Content constructorDetails = new ContentBuilder(constructorDetailsTreeHeader, constructorDetailsTree); + return getMemberTree(HtmlTree.SECTION(HtmlStyle.constructorDetails, constructorDetails)); } /** @@ -295,7 +298,7 @@ } else if (utils.isPrivate(member)) { code.add("private "); } else if (utils.isPublic(member)) { - code.add(Contents.SPACE); + code.add(Entity.NO_BREAK_SPACE); } else { code.add( resources.getText("doclet.Package_private")); @@ -303,4 +306,9 @@ tdSummaryType.add(code); } } + + @Override + public Content getMemberTreeHeader(){ + return writer.getMemberTreeHeader(); + } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java 2019-04-24 19:25:41.000000000 +0000 @@ -32,8 +32,8 @@ import jdk.javadoc.internal.doclets.formats.html.markup.Comment; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.FixedStringContent; -import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.Resources; @@ -52,8 +52,6 @@ * only created once per doclet-instance, instead of once per generated page. */ public class Contents { - public static final Content SPACE = RawHtml.nbsp; - public static final Content ZERO_WIDTH_SPACE = RawHtml.zws; public final Content allClassesLabel; public final Content allImplementedInterfacesLabel; @@ -400,7 +398,7 @@ int p; while ((p = text.indexOf(" ", start)) != -1) { c.add(text.substring(start, p)); - c.add(RawHtml.nbsp); + c.add(Entity.NO_BREAK_SPACE); start = p + 1; } c.add(text.substring(start)); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -26,17 +26,17 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.EnumConstantWriter; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; @@ -70,7 +70,7 @@ public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { memberSummaryTree.add(MarkerComments.START_OF_ENUM_CONSTANT_SUMMARY); - Content memberTree = writer.getMemberTreeHeader(); + Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, typeElement, memberTree); return memberTree; } @@ -80,7 +80,7 @@ */ @Override public void addMemberTree(Content memberSummaryTree, Content memberTree) { - writer.addMemberTree(memberSummaryTree, memberTree); + writer.addMemberTree(HtmlStyle.constantsSummary, memberSummaryTree, memberTree); } /** @@ -90,12 +90,12 @@ public Content getEnumConstantsDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) { memberDetailsTree.add(MarkerComments.START_OF_ENUM_CONSTANT_DETAILS); - Content enumConstantsDetailsTree = writer.getMemberTreeHeader(); - enumConstantsDetailsTree.add(links.createAnchor( - SectionName.ENUM_CONSTANT_DETAIL)); + Content enumConstantsDetailsTree = new ContentBuilder(); Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.enumConstantDetailLabel); enumConstantsDetailsTree.add(heading); + enumConstantsDetailsTree.add(links.createAnchor( + SectionName.ENUM_CONSTANT_DETAIL)); return enumConstantsDetailsTree; } @@ -105,12 +105,12 @@ @Override public Content getEnumConstantsTreeHeader(VariableElement enumConstant, Content enumConstantsDetailsTree) { - enumConstantsDetailsTree.add(links.createAnchor(name(enumConstant))); - Content enumConstantsTree = writer.getMemberTreeHeader(); + Content enumConstantsTree = new ContentBuilder(); Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING); heading.add(name(enumConstant)); enumConstantsTree.add(heading); - return enumConstantsTree; + enumConstantsTree.add(links.createAnchor(name(enumConstant))); + return HtmlTree.SECTION(HtmlStyle.detail, enumConstantsTree); } /** @@ -162,8 +162,11 @@ * {@inheritDoc} */ @Override - public Content getEnumConstantsDetails(Content enumConstantsDetailsTree) { - return HtmlTree.SECTION(getMemberTree(enumConstantsDetailsTree)); + public Content getEnumConstantsDetails(Content enumConstantsDetailsTreeHeader, + Content enumConstantsDetailsTree) { + Content enumConstantsDetails = + new ContentBuilder(enumConstantsDetailsTreeHeader, enumConstantsDetailsTree); + return getMemberTree(HtmlTree.SECTION(HtmlStyle.constantDetails, enumConstantsDetails)); } /** @@ -261,4 +264,9 @@ String name = utils.getFullyQualifiedName(member) + "." + member.getSimpleName(); return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, name); } + + @Override + public Content getMemberTreeHeader(){ + return writer.getMemberTreeHeader(); + } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,9 +25,6 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - import java.util.Arrays; import java.util.List; @@ -35,10 +32,14 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.FieldWriter; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; @@ -74,7 +75,7 @@ public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { memberSummaryTree.add(MarkerComments.START_OF_FIELD_SUMMARY); - Content memberTree = writer.getMemberTreeHeader(); + Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, typeElement, memberTree); return memberTree; } @@ -84,7 +85,7 @@ */ @Override public void addMemberTree(Content memberSummaryTree, Content memberTree) { - writer.addMemberTree(memberSummaryTree, memberTree); + writer.addMemberTree(HtmlStyle.fieldSummary, memberSummaryTree, memberTree); } /** @@ -93,12 +94,12 @@ @Override public Content getFieldDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) { memberDetailsTree.add(MarkerComments.START_OF_FIELD_DETAILS); - Content fieldDetailsTree = writer.getMemberTreeHeader(); - fieldDetailsTree.add(links.createAnchor( - SectionName.FIELD_DETAIL)); + Content fieldDetailsTree = new ContentBuilder(); Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.fieldDetailsLabel); fieldDetailsTree.add(heading); + fieldDetailsTree.add(links.createAnchor( + SectionName.FIELD_DETAIL)); return fieldDetailsTree; } @@ -107,12 +108,12 @@ */ @Override public Content getFieldDocTreeHeader(VariableElement field, Content fieldDetailsTree) { - fieldDetailsTree.add(links.createAnchor(name(field))); - Content fieldTree = writer.getMemberTreeHeader(); + Content fieldTree = new ContentBuilder(); Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING); heading.add(name(field)); fieldTree.add(heading); - return fieldTree; + fieldTree.add(links.createAnchor(name(field))); + return HtmlTree.SECTION(HtmlStyle.detail, fieldTree); } /** @@ -166,8 +167,9 @@ * {@inheritDoc} */ @Override - public Content getFieldDetails(Content fieldDetailsTree) { - return HtmlTree.SECTION(getMemberTree(fieldDetailsTree)); + public Content getFieldDetails(Content fieldDetailsTreeHeader, Content fieldDetailsTree) { + Content fieldDetails = new ContentBuilder(fieldDetailsTreeHeader, fieldDetailsTree); + return getMemberTree(HtmlTree.SECTION(HtmlStyle.fieldDetails, fieldDetails)); } /** @@ -247,7 +249,7 @@ } Content labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING, label); - labelHeading.add(Contents.SPACE); + labelHeading.add(Entity.NO_BREAK_SPACE); labelHeading.add(classLink); inheritedTree.add(labelHeading); } @@ -290,4 +292,9 @@ String name = utils.getFullyQualifiedName(member) + "." + member.getSimpleName(); return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, name); } + + @Override + public Content getMemberTreeHeader(){ + return writer.getMemberTreeHeader(); + } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -127,7 +127,7 @@ if (configuration.createoverview) { Content overviewHeading = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.overviewLabel); - htmlTree = HtmlTree.SECTION(overviewHeading); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, overviewHeading); String overviewKey = configuration.showModules ? "doclet.help.overview.modules.body" : "doclet.help.overview.packages.body"; @@ -143,7 +143,7 @@ if (configuration.showModules) { Content moduleHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.moduleLabel); - htmlTree = HtmlTree.SECTION(moduleHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, moduleHead); Content moduleIntro = contents.getContent("doclet.help.module.intro"); Content modulePara = HtmlTree.P(moduleIntro); htmlTree.add(modulePara); @@ -158,7 +158,7 @@ // Package Content packageHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.packageLabel); - htmlTree = HtmlTree.SECTION(packageHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, packageHead); Content packageIntro = contents.getContent("doclet.help.package.intro"); Content packagePara = HtmlTree.P(packageIntro); htmlTree.add(packagePara); @@ -175,7 +175,7 @@ // Class/interface Content classHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.getContent("doclet.help.class_interface.head")); - htmlTree = HtmlTree.SECTION(classHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, classHead); Content classIntro = contents.getContent("doclet.help.class_interface.intro"); Content classPara = HtmlTree.P(classIntro); htmlTree.add(classPara); @@ -210,7 +210,7 @@ // Annotation Types Content aHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.annotationType); - htmlTree = HtmlTree.SECTION(aHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, aHead); Content aIntro = contents.getContent("doclet.help.annotation_type.intro"); Content aPara = HtmlTree.P(aIntro); htmlTree.add(aPara); @@ -225,7 +225,7 @@ // Enums Content enumHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.enum_); - htmlTree = HtmlTree.SECTION(enumHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, enumHead); Content eIntro = contents.getContent("doclet.help.enum.intro"); Content enumPara = HtmlTree.P(eIntro); htmlTree.add(enumPara); @@ -241,7 +241,7 @@ if (configuration.classuse) { Content useHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.getContent("doclet.help.use.head")); - htmlTree = HtmlTree.SECTION(useHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, useHead); Content useBody = contents.getContent("doclet.help.use.body"); Content usePara = HtmlTree.P(useBody); htmlTree.add(usePara); @@ -252,7 +252,7 @@ if (configuration.createtree) { Content treeHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.getContent("doclet.help.tree.head")); - htmlTree = HtmlTree.SECTION(treeHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, treeHead); Content treeIntro = contents.getContent("doclet.help.tree.intro", links.createLink(DocPaths.OVERVIEW_TREE, resources.getText("doclet.Class_Hierarchy")), @@ -270,7 +270,7 @@ if (!(configuration.nodeprecatedlist || configuration.nodeprecated)) { Content dHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.deprecatedAPI); - htmlTree = HtmlTree.SECTION(dHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, dHead); Content deprBody = contents.getContent("doclet.help.deprecated.body", links.createLink(DocPaths.DEPRECATED_LIST, resources.getText("doclet.Deprecated_API"))); @@ -291,7 +291,7 @@ } Content indexHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.getContent("doclet.help.index.head")); - htmlTree = HtmlTree.SECTION(indexHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, indexHead); Content indexBody = contents.getContent("doclet.help.index.body", indexlink); Content indexPara = HtmlTree.P(indexBody); htmlTree.add(indexPara); @@ -301,7 +301,7 @@ // Serialized Form Content sHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.serializedForm); - htmlTree = HtmlTree.SECTION(sHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, sHead); Content serialBody = contents.getContent("doclet.help.serial_form.body"); Content serialPara = HtmlTree.P(serialBody); htmlTree.add(serialPara); @@ -310,7 +310,7 @@ // Constant Field Values Content constHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.constantsSummaryTitle); - htmlTree = HtmlTree.SECTION(constHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, constHead); Content constantsBody = contents.getContent("doclet.help.constants.body", links.createLink(DocPaths.CONSTANT_VALUES, resources.getText("doclet.Constants_Summary"))); @@ -321,7 +321,7 @@ // Search Content searchHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.getContent("doclet.help.search.head")); - htmlTree = HtmlTree.SECTION(searchHead); + htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, searchHead); Content searchBody = contents.getContent("doclet.help.search.body"); Content searchPara = HtmlTree.P(searchBody); htmlTree.add(searchPara); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java 2019-04-24 19:25:41.000000000 +0000 @@ -347,7 +347,7 @@ } } } - docPaths = new DocPaths(utils, useModuleDirectories); + docPaths = new DocPaths(utils); setCreateOverview(); setTopFile(docEnv); workArounds.initDocLint(doclintOpts.values(), tagletManager.getAllTagletNames()); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,11 +25,13 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Head; -import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Locale; +import java.util.Map; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -69,8 +71,10 @@ import com.sun.source.doctree.SystemPropertyTree; import com.sun.source.doctree.TextTree; import com.sun.source.util.SimpleDocTreeVisitor; - import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; +import jdk.javadoc.internal.doclets.formats.html.markup.Head; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; @@ -79,6 +83,7 @@ import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; import jdk.javadoc.internal.doclets.formats.html.markup.Script; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter; import jdk.javadoc.internal.doclets.toolkit.ClassWriter; import jdk.javadoc.internal.doclets.toolkit.Content; @@ -97,7 +102,12 @@ import jdk.javadoc.internal.doclets.toolkit.util.Utils; import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable; -import static com.sun.source.doctree.DocTree.Kind.*; +import static com.sun.source.doctree.DocTree.Kind.CODE; +import static com.sun.source.doctree.DocTree.Kind.COMMENT; +import static com.sun.source.doctree.DocTree.Kind.LINK; +import static com.sun.source.doctree.DocTree.Kind.LINK_PLAIN; +import static com.sun.source.doctree.DocTree.Kind.SEE; +import static com.sun.source.doctree.DocTree.Kind.TEXT; import static jdk.javadoc.internal.doclets.toolkit.util.CommentHelper.SPACER; @@ -417,7 +427,6 @@ .setCharset(configuration.charset) .addKeywords(metakeywords) .setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets()) - .setUseModuleDirectories(configuration.useModuleDirectories) .setIndex(configuration.createindex, mainBodyScript) .addContent(extraHeadContent); @@ -503,7 +512,7 @@ */ public Content getTableCaption(Content title) { Content captionSpan = HtmlTree.SPAN(title); - Content space = Contents.SPACE; + Content space = Entity.NO_BREAK_SPACE; Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space); Content caption = HtmlTree.CAPTION(captionSpan); caption.add(tabSpan); @@ -1227,7 +1236,7 @@ htmltree.add(div); } if (tags.isEmpty()) { - htmltree.add(Contents.SPACE); + htmltree.add(Entity.NO_BREAK_SPACE); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -103,15 +103,14 @@ * @return a content tree for the serializable fields content */ public Content getSerializableFields(String heading, Content serializableFieldsTree) { - HtmlTree li = new HtmlTree(HtmlTag.LI); - li.setStyle(HtmlStyle.blockList); + HtmlTree section = HtmlTree.SECTION(HtmlStyle.detail); if (serializableFieldsTree.isValid()) { Content headingContent = new StringContent(heading); Content serialHeading = HtmlTree.HEADING(Headings.SerializedForm.CLASS_SUBHEADING, headingContent); - li.add(serialHeading); - li.add(serializableFieldsTree); + section.add(serialHeading); + section.add(serializableFieldsTree); } - return li; + return HtmlTree.LI(HtmlStyle.blockList, section); } @Override diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -95,9 +95,9 @@ public Content getSerializableMethods(String heading, Content serializableMethodContent) { Content headingContent = new StringContent(heading); Content serialHeading = HtmlTree.HEADING(Headings.SerializedForm.CLASS_SUBHEADING, headingContent); - Content li = HtmlTree.LI(HtmlStyle.blockList, serialHeading); - li.add(serializableMethodContent); - return li; + Content section = HtmlTree.SECTION(HtmlStyle.detail, serialHeading); + section.add(serializableMethodContent); + return HtmlTree.LI(HtmlStyle.blockList, section); } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -35,6 +35,7 @@ import javax.lang.model.type.TypeMirror; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.Resources; @@ -162,7 +163,7 @@ for (TypeMirror t : vars) { if (many) { links.add(","); - links.add(Contents.ZERO_WIDTH_SPACE); + links.add(Entity.ZERO_WIDTH_SPACE); } links.add(getTypeParameterLink(linkInfo, t)); many = true; diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Entity.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Entity.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Entity.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Entity.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import jdk.javadoc.internal.doclets.toolkit.Content; + +import java.io.IOException; +import java.io.Writer; + +/** + * A representation of HTML entities. + */ +public class Entity extends Content { + public static final Entity LESS_THAN = new Entity("<"); + public static final Entity GREATER_THAN = new Entity(">"); + public static final Entity AMPERSAND = new Entity("&"); + public static final Entity NO_BREAK_SPACE = new Entity(" "); + public static final Entity ZERO_WIDTH_SPACE = new Entity("​") { + @Override + public int charCount() { + return 0; + } + }; + + public final String text; + + private Entity(String text) { + this.text = text; + } + + @Override + public void add(Content content) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(CharSequence stringContent) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean write(Writer writer, boolean atNewline) throws IOException { + writer.write(text); + return false; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public int charCount() { + return 1; + } + + + /** + * Escapes the special HTML characters in a given string using the appropriate + * entities. + * + * @param s the string to escape + * @return the string with all of the HTML characters escaped + */ + static String escapeHtmlChars(CharSequence s) { + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + // only start building a new string if we need to + case '<': case '>': case '&': + StringBuilder sb = new StringBuilder(s.subSequence(0, i)); + escapeHtmlChars(s, i, sb); + return sb.toString(); + } + } + return s.toString(); + } + + /** + * Escapes the special HTML characters in a given string using the appropriate + * entities, appending the results into a string builder. + * + * @param s the string + * @param sb the string builder + */ + static void escapeHtmlChars(CharSequence s, StringBuilder sb) { + escapeHtmlChars(s, 0, sb); + } + + private static void escapeHtmlChars(CharSequence s, int start, StringBuilder sb) { + for (int i = start ; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + case '<': sb.append(Entity.LESS_THAN.text); break; + case '>': sb.append(Entity.GREATER_THAN.text); break; + case '&': sb.append(Entity.AMPERSAND.text); break; + default: sb.append(ch); break; + } + } + } + +} diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/FixedStringContent.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/FixedStringContent.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/FixedStringContent.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/FixedStringContent.java 2019-04-24 19:25:41.000000000 +0000 @@ -47,9 +47,7 @@ * @param content content for the object */ public FixedStringContent(CharSequence content) { - string = needEscape(content) - ? escape(content) - : content.toString(); + string = Entity.escapeHtmlChars(content); } /** @@ -105,29 +103,4 @@ return string.endsWith(DocletConstants.NL); } - private boolean needEscape(CharSequence cs) { - for (int i = 0; i < cs.length(); i++) { - switch (cs.charAt(i)) { - case '<': - case '>': - case '&': - return true; - } - } - return false; - } - private String escape(CharSequence s) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - switch (ch) { - case '<': sb.append("<"); break; - case '>': sb.append(">"); break; - case '&': sb.append("&"); break; - default: sb.append(ch); break; - } - } - return sb.toString(); - } - } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java 2019-04-24 19:25:41.000000000 +0000 @@ -59,7 +59,6 @@ private String description; private String generator; private boolean showTimestamp; - private boolean useModuleDirectories; private DocFile mainStylesheetFile; private List additionalStylesheetFiles = Collections.emptyList(); private boolean index; @@ -170,17 +169,6 @@ } /** - * Sets whether the module directories should be used. This is used to set the JavaScript variable. - * - * @param useModuleDirectories true if the module directories should be used - * @return this object - */ - public Head setUseModuleDirectories(boolean useModuleDirectories) { - this.useModuleDirectories = useModuleDirectories; - return this; - } - - /** * Sets whether or not to include the supporting scripts and stylesheets for the * "search" feature. * If the feature is enabled, a {@code Script} must be provided into which some @@ -330,7 +318,6 @@ mainBodyScript.append("var pathtoroot = ") .appendStringLiteral(ptrPath + "/") .append(";\n") - .append("var useModuleDirectories = " + useModuleDirectories + ";\n") .append("loadScripts(document, \'script\');"); } addJQueryFile(tree, DocPaths.JSZIP_MIN); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java 2019-04-24 19:25:41.000000000 +0000 @@ -48,12 +48,16 @@ bottomNav, circle, classUseContainer, + classUses, colConstructorName, colDeprecatedItemName, colFirst, colLast, colSecond, constantsSummary, + constructorDetails, + constructorSummary, + constantDetails, constantValuesContainer, contentContainer, deprecatedLabel, @@ -63,40 +67,58 @@ description, descfrmTypeLabel, details, + detail, docSummary, emphasizedPhrase, externalLink, + fieldDetails, + fieldSummary, fixedNav, header, + helpSection, + hierarchy, horizontal, footer, implementationLabel, indexContainer, indexNav, inheritance, + inheritedList, interfaceName, leftContainer, leftTop, leftBottom, legalCopy, mainContainer, + memberDetails, memberNameLabel, memberNameLink, memberSummary, + methodDetails, methodSignature, + methodSummary, + moduleDescription, moduleLabelInPackage, moduleLabelInType, + moduleTags, + modulesSummary, nameValue, navBarCell1Rev, navList, navListSearch, navPadding, + nestedClassSummary, overrideSpecifyLabel, overviewSummary, + packages, + packageDescription, packageHierarchyLabel, packageLabelInType, packagesSummary, + packageUses, paramLabel, + propertyDetails, + propertySummary, providesSummary, requiresSummary, returnLabel, @@ -107,6 +129,9 @@ searchTagResult, seeLabel, serializedFormContainer, + serializedPackageContainer, + serializedClassDetails, + servicesSummary, simpleTagLabel, skipNav, sourceContainer, diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java 2019-04-24 19:25:41.000000000 +0000 @@ -100,7 +100,7 @@ public HtmlTree put(HtmlAttr attrName, String attrValue) { if (attrs.isEmpty()) attrs = new LinkedHashMap<>(3); - attrs.put(nullCheck(attrName), escapeHtmlChars(attrValue)); + attrs.put(nullCheck(attrName), Entity.escapeHtmlChars(attrValue)); return this; } @@ -188,35 +188,6 @@ return n; } - /** - * Given a string, escape all special HTML characters and - * return the result. - * - * @param s The string to check. - * @return the original string with all of the HTML characters escaped. - */ - private static String escapeHtmlChars(String s) { - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - switch (ch) { - // only start building a new string if we need to - case '<': case '>': case '&': - StringBuilder sb = new StringBuilder(s.substring(0, i)); - for ( ; i < s.length(); i++) { - ch = s.charAt(i); - switch (ch) { - case '<': sb.append("<"); break; - case '>': sb.append(">"); break; - case '&': sb.append("&"); break; - default: sb.append(ch); break; - } - } - return sb.toString(); - } - } - return s; - } - /* * The sets of ASCII URI characters to be left unencoded. * See "Uniform Resource Identifier (URI): Generic Syntax" @@ -717,22 +688,30 @@ } /** - * Generates a SECTION tag with role attribute. + * Generates a SECTION tag with style class attribute. * + * @param styleClass the style class for the tag * @return an HtmlTree object for the SECTION tag */ - public static HtmlTree SECTION() { - return new HtmlTree(HtmlTag.SECTION); + public static HtmlTree SECTION(HtmlStyle styleClass) { + HtmlTree htmlTree = new HtmlTree(HtmlTag.SECTION); + htmlTree.setStyle(styleClass); + return htmlTree; } /** - * Generates a SECTION tag with role attribute and some content. + * Generates a SECTION tag with style class attribute and some content. * + * @param styleClass the style class for the tag * @param body content of the section tag * @return an HtmlTree object for the SECTION tag */ - public static HtmlTree SECTION(Content body) { - return new HtmlTree(HtmlTag.SECTION, nullCheck(body)); + public static HtmlTree SECTION(HtmlStyle styleClass, Content body) { + HtmlTree htmlTree = new HtmlTree(HtmlTag.SECTION, nullCheck(body)); + if (styleClass != null) { + htmlTree.setStyle(styleClass); + } + return htmlTree; } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java 2019-04-24 19:25:41.000000000 +0000 @@ -429,7 +429,7 @@ } if (!listContents.isEmpty()) { Content li = HtmlTree.LI(contents.summaryLabel); - li.add(Contents.SPACE); + li.add(Entity.NO_BREAK_SPACE); tree.add(li); addListToNav(listContents, tree); } @@ -461,7 +461,7 @@ } if (!listContents.isEmpty()) { Content li = HtmlTree.LI(contents.moduleSubNavLabel); - li.add(Contents.SPACE); + li.add(Entity.NO_BREAK_SPACE); tree.add(li); addListToNav(listContents, tree); } @@ -665,7 +665,7 @@ } if (!listContents.isEmpty()) { Content li = HtmlTree.LI(contents.detailLabel); - li.add(Contents.SPACE); + li.add(Entity.NO_BREAK_SPACE); tree.add(li); addListToNav(listContents, tree); } @@ -801,9 +801,9 @@ int count = 0; for (Content liContent : listContents) { if (count < listContents.size() - 1) { - liContent.add(Contents.SPACE); + liContent.add(Entity.NO_BREAK_SPACE); liContent.add("|"); - liContent.add(Contents.SPACE); + liContent.add(Entity.NO_BREAK_SPACE); } tree.add(liContent); count++; @@ -935,11 +935,10 @@ String reset = "reset"; HtmlTree inputText = HtmlTree.INPUT("text", searchValueId, searchValueId); HtmlTree inputReset = HtmlTree.INPUT(reset, reset, reset); - HtmlTree liInput = HtmlTree.LI(HtmlTree.LABEL(searchValueId, searchLabel)); - liInput.add(inputText); - liInput.add(inputReset); - HtmlTree ulSearch = HtmlTree.UL(HtmlStyle.navListSearch, liInput); - tree.add(ulSearch); + HtmlTree searchDiv = HtmlTree.DIV(HtmlStyle.navListSearch, HtmlTree.LABEL(searchValueId, searchLabel)); + searchDiv.add(inputText); + searchDiv.add(inputReset); + tree.add(searchDiv); } private void addFixedNavScript(Content tree) { @@ -1006,7 +1005,7 @@ fixedNavDiv.add(queue.poll()); fixedNavDiv.add(Position.TOP.endOfNav()); tree.add(fixedNavDiv); - HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Contents.SPACE); + HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Entity.NO_BREAK_SPACE); tree.add(paddingDiv); addFixedNavScript(tree); } else { diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java 2019-04-24 19:25:41.000000000 +0000 @@ -45,10 +45,6 @@ private final String rawHtmlContent; - public static final Content nbsp = new RawHtml(" "); - - public static final Content zws = new RawHtml("​"); - /** * Constructor to construct a RawHtml object. * diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java 2019-04-24 19:25:41.000000000 +0000 @@ -59,7 +59,7 @@ */ public StringContent(CharSequence initialContent) { stringContent = new StringBuilder(); - appendChars(initialContent); + Entity.escapeHtmlChars(initialContent, stringContent); } /** @@ -81,7 +81,7 @@ */ @Override public void add(CharSequence strContent) { - appendChars(strContent); + Entity.escapeHtmlChars(strContent, stringContent); } /** @@ -114,16 +114,4 @@ out.write(s); return s.endsWith(DocletConstants.NL); } - - private void appendChars(CharSequence s) { - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - switch (ch) { - case '<': stringContent.append("<"); break; - case '>': stringContent.append(">"); break; - case '&': stringContent.append("&"); break; - default: stringContent.append(ch); break; - } - } - } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java 2019-04-24 19:25:41.000000000 +0000 @@ -531,6 +531,6 @@ private HtmlTree getCaption(Content title) { return new HtmlTree(HtmlTag.CAPTION, HtmlTree.SPAN(title), - HtmlTree.SPAN(tabEnd, Contents.SPACE)); + HtmlTree.SPAN(tabEnd, Entity.NO_BREAK_SPACE)); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,9 +25,6 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - import java.util.SortedSet; import java.util.TreeSet; @@ -36,10 +33,14 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.MethodWriter; @@ -87,7 +88,7 @@ @Override public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { memberSummaryTree.add(MarkerComments.START_OF_METHOD_SUMMARY); - Content memberTree = writer.getMemberTreeHeader(); + Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, typeElement, memberTree); return memberTree; } @@ -97,7 +98,7 @@ */ @Override public void addMemberTree(Content memberSummaryTree, Content memberTree) { - writer.addMemberTree(memberSummaryTree, memberTree); + writer.addMemberTree(HtmlStyle.methodSummary, memberSummaryTree, memberTree); } /** @@ -106,11 +107,11 @@ @Override public Content getMethodDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) { memberDetailsTree.add(MarkerComments.START_OF_METHOD_DETAILS); - Content methodDetailsTree = writer.getMemberTreeHeader(); - methodDetailsTree.add(links.createAnchor(SectionName.METHOD_DETAIL)); + Content methodDetailsTree = new ContentBuilder(); Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.methodDetailLabel); methodDetailsTree.add(heading); + methodDetailsTree.add(links.createAnchor(SectionName.METHOD_DETAIL)); return methodDetailsTree; } @@ -120,15 +121,15 @@ @Override public Content getMethodDocTreeHeader(ExecutableElement method, Content methodDetailsTree) { String erasureAnchor; - if ((erasureAnchor = getErasureAnchor(method)) != null) { - methodDetailsTree.add(links.createAnchor((erasureAnchor))); - } - methodDetailsTree.add(links.createAnchor(writer.getAnchor(method))); - Content methodDocTree = writer.getMemberTreeHeader(); + Content methodDocTree = new ContentBuilder(); Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING); heading.add(name(method)); methodDocTree.add(heading); - return methodDocTree; + if ((erasureAnchor = getErasureAnchor(method)) != null) { + methodDocTree.add(links.createAnchor((erasureAnchor))); + } + methodDocTree.add(links.createAnchor(writer.getAnchor(method))); + return HtmlTree.SECTION(HtmlStyle.detail, methodDocTree); } /** @@ -190,7 +191,7 @@ utils.isClass(holder) ? contents.descfrmClassLabel : contents.descfrmInterfaceLabel); - descfrmLabel.add(Contents.SPACE); + descfrmLabel.add(Entity.NO_BREAK_SPACE); descfrmLabel.add(codelLink); methodDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel)); writer.addInlineComment(method, methodDocTree); @@ -210,8 +211,9 @@ * {@inheritDoc} */ @Override - public Content getMethodDetails(Content methodDetailsTree) { - return HtmlTree.SECTION(getMemberTree(methodDetailsTree)); + public Content getMethodDetails(Content methodDetailsTreeHeader, Content methodDetailsTree) { + Content methodDetails = new ContentBuilder(methodDetailsTreeHeader, methodDetailsTree); + return getMemberTree(HtmlTree.SECTION(HtmlStyle.methodDetails, methodDetails)); } /** @@ -296,7 +298,7 @@ } Content labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING, label); - labelHeading.add(Contents.SPACE); + labelHeading.add(Entity.NO_BREAK_SPACE); labelHeading.add(classLink); inheritedTree.add(labelHeading); } @@ -352,9 +354,9 @@ .where(writer.links.getName(writer.getAnchor(method))).label(method.getSimpleName())); Content codeMethLink = HtmlTree.CODE(methlink); Content dd = HtmlTree.DD(codeMethLink); - dd.add(Contents.SPACE); + dd.add(Entity.NO_BREAK_SPACE); dd.add(writer.contents.inClass); - dd.add(Contents.SPACE); + dd.add(Entity.NO_BREAK_SPACE); dd.add(codeOverridenTypeLink); dl.add(dd); } @@ -388,9 +390,9 @@ implementedMeth.getSimpleName(), false); Content codeMethLink = HtmlTree.CODE(methlink); Content dd = HtmlTree.DD(codeMethLink); - dd.add(Contents.SPACE); + dd.add(Entity.NO_BREAK_SPACE); dd.add(contents.inInterface); - dd.add(Contents.SPACE); + dd.add(Entity.NO_BREAK_SPACE); dd.add(codeIntfacLink); dl.add(dd); } @@ -408,7 +410,12 @@ Content linkContent = writer.getLink( new LinkInfoImpl(configuration, LinkInfoImpl.Kind.RETURN_TYPE, type)); htmltree.add(linkContent); - htmltree.add(Contents.SPACE); + htmltree.add(Entity.NO_BREAK_SPACE); } } + + @Override + public Content getMemberTreeHeader(){ + return writer.getMemberTreeHeader(); + } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,9 +25,6 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -46,6 +43,7 @@ import com.sun.source.doctree.DocTree; import jdk.javadoc.doclet.DocletEnvironment.ModuleMode; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -53,6 +51,8 @@ import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; @@ -166,11 +166,6 @@ */ protected HtmlTree mainTree = HtmlTree.MAIN(); - /** - * The HTML tree for section tag. - */ - protected HtmlTree sectionTree = HtmlTree.SECTION(); - private final Navigation navBar; /** @@ -214,7 +209,7 @@ ? contents.openModuleLabel : contents.moduleLabel; Content tHeading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true, HtmlStyle.title, label); - tHeading.add(Contents.SPACE); + tHeading.add(Entity.NO_BREAK_SPACE); Content moduleHead = new RawHtml(heading); tHeading.add(moduleHead); div.add(tHeading); @@ -237,9 +232,9 @@ */ @Override public Content getSummaryHeader() { - HtmlTree li = new HtmlTree(HtmlTag.LI); - li.setStyle(HtmlStyle.blockList); - return li; + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.setStyle(HtmlStyle.blockList); + return ul; } /** @@ -249,8 +244,7 @@ */ @Override public Content getSummaryTree(Content summaryContentTree) { - HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree); - return ul; + return HtmlTree.SECTION(HtmlStyle.summary, summaryContentTree); } /** @@ -506,10 +500,9 @@ TableHeader requiresTableHeader = new TableHeader(contents.modifierLabel, contents.moduleLabel, contents.descriptionLabel); - HtmlTree li = new HtmlTree(HtmlTag.LI); - li.setStyle(HtmlStyle.blockList); + HtmlTree section = HtmlTree.SECTION(HtmlStyle.modulesSummary); addSummaryHeader(MarkerComments.START_OF_MODULES_SUMMARY, SectionName.MODULES, - contents.navModules, li); + contents.navModules, section); if (display(requires)) { String text = resources.getText("doclet.Requires_Summary"); String tableSummary = resources.getText("doclet.Member_Table_Summary", @@ -519,7 +512,7 @@ Table table = getTable3(caption, tableSummary, HtmlStyle.requiresSummary, requiresTableHeader); addModulesList(requires, table); - li.add(table.toContent()); + section.add(table.toContent()); } // Display indirect modules table in both "api" and "all" mode. if (display(indirectModules)) { @@ -531,10 +524,9 @@ Table amrTable = getTable3(amrCaption, amrTableSummary, HtmlStyle.requiresSummary, requiresTableHeader); addModulesList(indirectModules, amrTable); - li.add(amrTable.toContent()); + section.add(amrTable.toContent()); } - HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); - summaryContentTree.add(ul); + summaryContentTree.add(HtmlTree.LI(HtmlStyle.blockList, section)); } } @@ -542,7 +534,7 @@ * Add the list of modules. * * @param mdleMap map of modules and modifiers - * @param tbody the content tree to which the list will be added + * @param table the table to which the list will be added */ private void addModulesList(Map mdleMap, Table table) { for (ModuleElement m : mdleMap.keySet()) { @@ -558,12 +550,11 @@ public void addPackagesSummary(Content summaryContentTree) { if (display(packages) || display(indirectPackages) || display(indirectOpenPackages)) { - HtmlTree li = new HtmlTree(HtmlTag.LI); - li.setStyle(HtmlStyle.blockList); + HtmlTree section = HtmlTree.SECTION(HtmlStyle.packagesSummary); addSummaryHeader(MarkerComments.START_OF_PACKAGES_SUMMARY, SectionName.PACKAGES, - contents.navPackages, li); + contents.navPackages, section); if (display(packages)) { - addPackageSummary(li); + addPackageSummary(section); } TableHeader indirectPackagesHeader = new TableHeader(contents.fromLabel, contents.packagesLabel); @@ -572,17 +563,16 @@ Table aepTable = getTable2(new StringContent(aepText), HtmlStyle.packagesSummary, indirectPackagesHeader); addIndirectPackages(aepTable, indirectPackages); - li.add(aepTable.toContent()); + section.add(aepTable.toContent()); } if (display(indirectOpenPackages)) { String aopText = resources.getText("doclet.Indirect_Opens_Summary"); Table aopTable = getTable2(new StringContent(aopText), HtmlStyle.packagesSummary, indirectPackagesHeader); addIndirectPackages(aopTable, indirectOpenPackages); - li.add(aopTable.toContent()); + section.add(aopTable.toContent()); } - HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); - summaryContentTree.add(ul); + summaryContentTree.add(HtmlTree.LI(HtmlStyle.blockList, section)); } } @@ -737,10 +727,9 @@ boolean haveProvides = displayServices(provides.keySet(), providesTrees); if (haveProvides || haveUses) { - HtmlTree li = new HtmlTree(HtmlTag.LI); - li.setStyle(HtmlStyle.blockList); + HtmlTree section = HtmlTree.SECTION(HtmlStyle.servicesSummary); addSummaryHeader(MarkerComments.START_OF_SERVICES_SUMMARY, SectionName.SERVICES, - contents.navServices, li); + contents.navServices, section); TableHeader usesProvidesTableHeader = new TableHeader(contents.typeLabel, contents.descriptionLabel); if (haveProvides) { @@ -749,7 +738,7 @@ usesProvidesTableHeader); addProvidesList(table); if (!table.isEmpty()) { - li.add(table.toContent()); + section.add(table.toContent()); } } if (haveUses){ @@ -758,11 +747,10 @@ usesProvidesTableHeader); addUsesList(table); if (!table.isEmpty()) { - li.add(table.toContent()); + section.add(table.toContent()); } } - HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); - summaryContentTree.add(ul); + summaryContentTree.add(HtmlTree.LI(HtmlStyle.blockList, section)); } } @@ -788,7 +776,7 @@ addSummaryComment(t, summary); } } else { - summary.add(Contents.SPACE); + summary.add(Entity.NO_BREAK_SPACE); } table.addRow(typeLinkContent, summary); } @@ -814,9 +802,9 @@ description = providesTrees.get(srv); desc.add((description != null && !description.isEmpty()) ? HtmlTree.DIV(HtmlStyle.block, description) - : Contents.SPACE); + : Entity.NO_BREAK_SPACE); } else { - desc.add(Contents.SPACE); + desc.add(Entity.NO_BREAK_SPACE); } // Only display the implementation details in the "all" mode. if (moduleMode == ModuleMode.ALL && !implSet.isEmpty()) { @@ -824,7 +812,7 @@ desc.add("("); HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation); desc.add(implSpan); - desc.add(Contents.SPACE); + desc.add(Entity.NO_BREAK_SPACE); String sep = ""; for (TypeElement impl : implSet) { desc.add(sep); @@ -866,7 +854,7 @@ @Override public void addModuleDescription(Content moduleContentTree) { if (!utils.getFullBody(mdle).isEmpty()) { - Content tree = HtmlTree.SECTION(); + Content tree = HtmlTree.SECTION(HtmlStyle.moduleDescription); addDeprecationInfo(tree); tree.add(MarkerComments.START_OF_MODULE_DESCRIPTION); tree.add(links.createAnchor(SectionName.MODULE_DESCRIPTION)); @@ -880,7 +868,7 @@ */ @Override public void addModuleTags(Content moduleContentTree) { - Content tree = HtmlTree.SECTION(); + Content tree = HtmlTree.SECTION(HtmlStyle.moduleTags); addTagsInfo(mdle, tree); moduleContentTree.add(tree); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,18 +25,19 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - import java.util.Arrays; import java.util.List; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; @@ -71,7 +72,7 @@ public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { memberSummaryTree.add(MarkerComments.START_OF_NESTED_CLASS_SUMMARY); - Content memberTree = writer.getMemberTreeHeader(); + Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, typeElement, memberTree); return memberTree; } @@ -81,7 +82,7 @@ */ @Override public void addMemberTree(Content memberSummaryTree, Content memberTree) { - writer.addMemberTree(memberSummaryTree, memberTree); + writer.addMemberTree(HtmlStyle.nestedClassSummary, memberSummaryTree, memberTree); } /** @@ -154,7 +155,7 @@ : resources.getText("doclet.Nested_Classes_Interfaces_Inherited_From_Class")); } Content labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, label); - labelHeading.add(Contents.SPACE); + labelHeading.add(Entity.NO_BREAK_SPACE); labelHeading.add(classLink); inheritedTree.add(labelHeading); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,21 +25,24 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - -import java.util.*; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper; import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; @@ -151,13 +154,12 @@ * @param contentTree the content tree to which the package use information will be added */ protected void addPackageUse(Content contentTree) { - HtmlTree ul = new HtmlTree(HtmlTag.UL); - ul.setStyle(HtmlStyle.blockList); + Content content = new ContentBuilder(); if (configuration.packages.size() > 1) { - addPackageList(ul); + addPackageList(content); } - addClassList(ul); - contentTree.add(ul); + addClassList(content); + contentTree.add(content); } /** @@ -181,12 +183,11 @@ if (pkg != null && !pkg.isUnnamed()) { addSummaryComment(pkg, summary); } else { - summary.add(Contents.SPACE); + summary.add(Entity.NO_BREAK_SPACE); } table.addRow(packageLink, summary); } - Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent()); - contentTree.add(li); + contentTree.add(table.toContent()); } /** @@ -197,11 +198,12 @@ protected void addClassList(Content contentTree) { TableHeader classTableHeader = new TableHeader( contents.classLabel, contents.descriptionLabel); + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.setStyle(HtmlStyle.blockList); for (String packageName : usingPackageToUsedClasses.keySet()) { PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName); - HtmlTree li = new HtmlTree(HtmlTag.LI); - li.setStyle(HtmlStyle.blockList); - li.add(links.createAnchor(getPackageAnchorName(usingPackage))); + HtmlTree section = HtmlTree.SECTION(HtmlStyle.detail); + section.add(links.createAnchor(getPackageAnchorName(usingPackage))); String tableSummary = resources.getText("doclet.Use_Table_Summary", resources.getText("doclet.classes")); Content caption = contents.getContent( @@ -223,9 +225,11 @@ table.addRow(typeContent, summary); } - li.add(table.toContent()); - contentTree.add(li); + section.add(table.toContent()); + ul.add(HtmlTree.LI(HtmlStyle.blockList, section)); } + Content li = HtmlTree.SECTION(HtmlStyle.packageUses, ul); + contentTree.add(li); } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,10 +25,8 @@ package jdk.javadoc.internal.doclets.formats.html; -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - -import java.util.*; +import java.util.List; +import java.util.SortedSet; import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; @@ -36,12 +34,15 @@ import com.sun.source.doctree.DocTree; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; @@ -77,7 +78,7 @@ /** * The HTML tree for section tag. */ - protected HtmlTree sectionTree = HtmlTree.SECTION(); + protected HtmlTree sectionTree = HtmlTree.SECTION(HtmlStyle.packageDescription, new ContentBuilder()); private final Navigation navBar; @@ -120,7 +121,7 @@ ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement); Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel); Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel); - moduleNameDiv.add(Contents.SPACE); + moduleNameDiv.add(Entity.NO_BREAK_SPACE); moduleNameDiv.add(getModuleLink(mdle, new StringContent(mdle.getQualifiedName().toString()))); div.add(moduleNameDiv); @@ -130,7 +131,7 @@ div.add(annotationContent); Content tHeading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true, HtmlStyle.title, contents.packageLabel); - tHeading.add(Contents.SPACE); + tHeading.add(Entity.NO_BREAK_SPACE); Content packageHead = new StringContent(heading); tHeading.add(packageHead); div.add(tHeading); @@ -320,4 +321,12 @@ printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement), description, stylesheetContent, contentTree); } + + /** + * {@inheritDoc} + */ + @Override + public Content getPackageSummary(Content summaryContentTree) { + return HtmlTree.SECTION(HtmlStyle.summary, summaryContentTree); + } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,23 +25,22 @@ package jdk.javadoc.internal.doclets.formats.html; - -import jdk.javadoc.internal.doclets.formats.html.markup.Table; -import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; - import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.formats.html.markup.Table; +import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.PropertyWriter; - /** * Writes property documentation in HTML format. * @@ -68,7 +67,7 @@ @Override public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { memberSummaryTree.add(MarkerComments.START_OF_PROPERTY_SUMMARY); - Content memberTree = writer.getMemberTreeHeader(); + Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, typeElement, memberTree); return memberTree; } @@ -78,7 +77,7 @@ */ @Override public void addMemberTree(Content memberSummaryTree, Content memberTree) { - writer.addMemberTree(memberSummaryTree, memberTree); + writer.addMemberTree(HtmlStyle.propertySummary, memberSummaryTree, memberTree); } /** @@ -88,11 +87,11 @@ public Content getPropertyDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) { memberDetailsTree.add(MarkerComments.START_OF_PROPERTY_DETAILS); - Content propertyDetailsTree = writer.getMemberTreeHeader(); - propertyDetailsTree.add(links.createAnchor(SectionName.PROPERTY_DETAIL)); + Content propertyDetailsTree = new ContentBuilder(); Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING, contents.propertyDetailsLabel); propertyDetailsTree.add(heading); + propertyDetailsTree.add(links.createAnchor(SectionName.PROPERTY_DETAIL)); return propertyDetailsTree; } @@ -102,12 +101,12 @@ @Override public Content getPropertyDocTreeHeader(ExecutableElement property, Content propertyDetailsTree) { - propertyDetailsTree.add(links.createAnchor(name(property))); - Content propertyDocTree = writer.getMemberTreeHeader(); + Content propertyDocTree = new ContentBuilder(); Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING); heading.add(utils.getPropertyLabel(name(property))); propertyDocTree.add(heading); - return propertyDocTree; + propertyDocTree.add(links.createAnchor(name(property))); + return HtmlTree.SECTION(HtmlStyle.detail, propertyDocTree); } /** @@ -161,7 +160,7 @@ utils.isClass(holder) ? contents.descfrmClassLabel : contents.descfrmInterfaceLabel); - descfrmLabel.add(Contents.SPACE); + descfrmLabel.add(Entity.NO_BREAK_SPACE); descfrmLabel.add(codeLink); propertyDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel)); writer.addInlineComment(property, propertyDocTree); @@ -181,8 +180,9 @@ * {@inheritDoc} */ @Override - public Content getPropertyDetails(Content propertyDetailsTree) { - return HtmlTree.SECTION(getMemberTree(propertyDetailsTree)); + public Content getPropertyDetails(Content propertyDetailsTreeHeader, Content propertyDetailsTree) { + Content propertyDetails = new ContentBuilder(propertyDetailsTreeHeader, propertyDetailsTree); + return getMemberTree(HtmlTree.SECTION(HtmlStyle.propertyDetails, propertyDetails)); } /** @@ -262,7 +262,7 @@ } Content labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING, label); - labelHeading.add(Contents.SPACE); + labelHeading.add(Entity.NO_BREAK_SPACE); labelHeading.add(classLink); inheritedTree.add(labelHeading); } @@ -312,4 +312,9 @@ return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, utils.getFullyQualifiedName(member)); } + + @Override + public Content getMemberTreeHeader(){ + return writer.getMemberTreeHeader(); + } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js 2019-04-24 19:25:41.000000000 +0000 @@ -47,22 +47,20 @@ } function getURLPrefix(ui) { var urlPrefix=""; - if (useModuleDirectories) { - var slash = "/"; - if (ui.item.category === catModules) { - return ui.item.l + slash; - } else if (ui.item.category === catPackages && ui.item.m) { - return ui.item.m + slash; - } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { - $.each(packageSearchIndex, function(index, item) { - if (item.m && ui.item.p == item.l) { - urlPrefix = item.m + slash; - } - }); - return urlPrefix; - } else { - return urlPrefix; - } + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (item.m && ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; } return urlPrefix; } @@ -286,11 +284,7 @@ if (ui.item.l !== noResult.l) { var url = getURLPrefix(ui); if (ui.item.category === catModules) { - if (useModuleDirectories) { - url += "module-summary.html"; - } else { - url = ui.item.l + "-summary.html"; - } + url += "module-summary.html"; } else if (ui.item.category === catPackages) { if (ui.item.url) { url = ui.item.url; diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,10 +25,11 @@ package jdk.javadoc.internal.doclets.formats.html; -import java.util.*; +import java.util.Set; import javax.lang.model.element.TypeElement; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -109,7 +110,7 @@ * @return the package serialized form header tree */ public Content getPackageSerializedHeader() { - return HtmlTree.SECTION(); + return HtmlTree.SECTION(HtmlStyle.serializedPackageContainer); } /** @@ -121,7 +122,7 @@ public Content getPackageHeader(String packageName) { Content heading = HtmlTree.HEADING(Headings.SerializedForm.PACKAGE_HEADING, true, contents.packageLabel); - heading.add(Contents.SPACE); + heading.add(Entity.NO_BREAK_SPACE); heading.add(packageName); return heading; } @@ -158,7 +159,7 @@ ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, typeElement) .label(configuration.getClassName(typeElement))) : new StringContent(utils.getFullyQualifiedName(typeElement)); - Content li = HtmlTree.LI(HtmlStyle.blockList, links.createAnchor( + Content section = HtmlTree.SECTION(HtmlStyle.serializedClassDetails, links.createAnchor( utils.getFullyQualifiedName(typeElement))); Content superClassLink = typeElement.getSuperclass() != null ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.SERIALIZED_FORM, @@ -172,8 +173,8 @@ contents.getContent( "doclet.Class_0_extends_implements_serializable", classLink, superClassLink); - li.add(HtmlTree.HEADING(Headings.SerializedForm.CLASS_HEADING, className)); - return li; + section.add(HtmlTree.HEADING(Headings.SerializedForm.CLASS_HEADING, className)); + return section; } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -25,8 +25,10 @@ package jdk.javadoc.internal.doclets.formats.html; -import java.util.*; +import java.util.Set; +import java.util.TreeSet; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -140,13 +142,13 @@ contentTree.add( links.createLink(getNameForIndex(unicode), new StringContent(unicode))); - contentTree.add(Contents.SPACE); + contentTree.add(Entity.NO_BREAK_SPACE); } contentTree.add(new HtmlTree(HtmlTag.BR)); contentTree.add(links.createLink(DocPaths.ALLCLASSES_INDEX, contents.allClassesLabel)); if (!configuration.packages.isEmpty()) { - contentTree.add(Contents.SPACE); + contentTree.add(Entity.NO_BREAK_SPACE); contentTree.add(links.createLink(DocPaths.ALLPACKAGES_INDEX, contents.allPackagesLabel)); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -32,6 +32,7 @@ import java.util.Set; import java.util.TreeSet; +import jdk.javadoc.internal.doclets.formats.html.markup.Entity; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -163,13 +164,13 @@ int j = i + 1; contentTree.add(links.createLink(DocPaths.indexN(j), new StringContent(indexElements.get(i).toString()))); - contentTree.add(Contents.SPACE); + contentTree.add(Entity.NO_BREAK_SPACE); } contentTree.add(new HtmlTree(HtmlTag.BR)); contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.ALLCLASSES_INDEX), contents.allClassesLabel)); if (!configuration.packages.isEmpty()) { - contentTree.add(Contents.SPACE); + contentTree.add(Entity.NO_BREAK_SPACE); contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.ALLPACKAGES_INDEX), contents.allPackagesLabel)); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -90,8 +90,8 @@ */ public void addInheritedSummaryHeader(AbstractMemberWriter mw, TypeElement typeElement, Content inheritedTree) { - mw.addInheritedSummaryAnchor(typeElement, inheritedTree); mw.addInheritedSummaryLabel(typeElement, inheritedTree); + mw.addInheritedSummaryAnchor(typeElement, inheritedTree); } /** @@ -212,23 +212,29 @@ /** * Get the member header tree * - * @return a content tree the member header + * @return a content tree for the member header */ public Content getMemberTreeHeader() { - HtmlTree li = new HtmlTree(HtmlTag.LI); - li.setStyle(HtmlStyle.blockList); - return li; + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.setStyle(HtmlStyle.blockList); + return ul; + } + + public Content getMemberInheritedTree() { + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.setStyle(HtmlStyle.inheritedList); + return div; } /** - * Add the member tree. - * + * Adds the member tree with css style. + * @param style the css style to be applied to member tree * @param memberSummaryTree the content tree representing the member summary * @param memberTree the content tree representing the member */ - public void addMemberTree(Content memberSummaryTree, Content memberTree) { - HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(memberTree)); - memberSummaryTree.add(htmlTree); + public void addMemberTree(HtmlStyle style, Content memberSummaryTree, Content memberTree) { + HtmlTree htmlTree = HtmlTree.SECTION(style, memberTree); + memberSummaryTree.add(getMemberTree(htmlTree)); } /** @@ -238,8 +244,7 @@ * @return a content tree for the member */ public Content getMemberTree(Content contentTree) { - Content ul = HtmlTree.UL(HtmlStyle.blockList, contentTree); - return ul; + return HtmlTree.LI(HtmlStyle.blockList, contentTree); } /** @@ -249,7 +254,7 @@ * @return a content tree for the member summary */ public Content getMemberSummaryTree(Content contentTree) { - return getMemberTree(HtmlStyle.summary, contentTree); + return HtmlTree.SECTION(HtmlStyle.summary, contentTree); } /** @@ -259,7 +264,7 @@ * @return a content tree for the member details */ public Content getMemberDetailsTree(Content contentTree) { - return getMemberTree(HtmlStyle.details, contentTree); + return HtmlTree.SECTION(HtmlStyle.details, contentTree); } /** @@ -270,7 +275,6 @@ * @return the member tree */ public Content getMemberTree(HtmlStyle style, Content contentTree) { - Content div = HtmlTree.DIV(style, getMemberTree(contentTree)); - return div; + return HtmlTree.SECTION(style, contentTree); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeFieldWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeFieldWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeFieldWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeFieldWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -62,10 +62,8 @@ * Add the annotation type details tree header. * * @param typeElement the annotation type being documented - * @param memberDetailsTree the content tree representing member details */ - public void addAnnotationDetailsTreeHeader(TypeElement typeElement, - Content memberDetailsTree); + public Content getAnnotationDetailsTreeHeader(TypeElement typeElement); /** * Get the annotation type documentation tree header. @@ -79,10 +77,11 @@ /** * Get the annotation type details tree. * + * @param annotationDetailsTreeHeader the content tree representing annotation type details header * @param annotationDetailsTree the content tree representing annotation type details * @return content tree for the annotation type details */ - public Content getAnnotationDetails(Content annotationDetailsTree); + public Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree); /** * Get the annotation type documentation. diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeRequiredMemberWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeRequiredMemberWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeRequiredMemberWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeRequiredMemberWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -61,10 +61,8 @@ * Add the annotation type details tree header. * * @param typeElement the annotation type being documented - * @param memberDetailsTree the content tree representing member details */ - public void addAnnotationDetailsTreeHeader(TypeElement typeElement, - Content memberDetailsTree); + public Content getAnnotationDetailsTreeHeader(TypeElement typeElement); /** * Get the annotation type documentation tree header. @@ -79,10 +77,11 @@ /** * Get the annotation type details tree. * + * @param annotationDetailsTreeHeader the content tree representing annotation type details header * @param annotationDetailsTree the content tree representing annotation type details * @return content tree for the annotation type details */ - public Content getAnnotationDetails(Content annotationDetailsTree); + public Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree); /** * Get the annotation type documentation. diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java 2019-04-24 19:25:41.000000000 +0000 @@ -295,12 +295,6 @@ // A list of pairs containing urls and package list private final List> linkOfflineList = new ArrayList<>(); - /** - * Flag to enable/disable use of module directories when generating docs for modules - * Default: on (module directories are enabled). - */ - public boolean useModuleDirectories = true; - public boolean dumpOnError = false; private List> groupPairs; @@ -748,13 +742,6 @@ showTaglets = true; return true; } - }, - new XOption(resources, "--no-module-directories") { - @Override - public boolean process(String option, List args) { - useModuleDirectories = false; - return true; - } } }; Set set = new TreeSet<>(); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -28,6 +28,7 @@ import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler; @@ -149,8 +150,7 @@ */ protected void buildAnnotationTypeInfo(Content annotationContentTree) throws DocletException { - Content annotationInfoTree = writer.getAnnotationInfoTreeHeader(); - + Content annotationInfoTree = new ContentBuilder(); buildAnnotationTypeSignature(annotationInfoTree); buildDeprecationInfo(annotationInfoTree); buildAnnotationTypeDescription(annotationInfoTree); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -139,12 +139,12 @@ } if (hasMembersToDocument()) { writer.addAnnotationFieldDetailsMarker(memberDetailsTree); + Content annotationDetailsTreeHeader = writer.getAnnotationDetailsTreeHeader(typeElement); + Content detailsTree = writer.getMemberTreeHeader(); Element lastElement = members.get(members.size() - 1); for (Element member : members) { currentMember = member; - Content detailsTree = writer.getMemberTreeHeader(); - writer.addAnnotationDetailsTreeHeader(typeElement, detailsTree); Content annotationDocTree = writer.getAnnotationDocTreeHeader(currentMember, detailsTree); @@ -155,8 +155,8 @@ detailsTree.add(writer.getAnnotationDoc( annotationDocTree, currentMember == lastElement)); - memberDetailsTree.add(writer.getAnnotationDetails(detailsTree)); } + memberDetailsTree.add(writer.getAnnotationDetails(annotationDetailsTreeHeader, detailsTree)); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -142,11 +142,11 @@ } if (hasMembersToDocument()) { writer.addAnnotationDetailsMarker(memberDetailsTree); + Content annotationDetailsTreeHeader = writer.getAnnotationDetailsTreeHeader(typeElement); + Content detailsTree = writer.getMemberTreeHeader(); Element lastMember = members.get((members.size() - 1)); for (Element member : members) { currentMember = member; - Content detailsTree = writer.getMemberTreeHeader(); - writer.addAnnotationDetailsTreeHeader(typeElement, detailsTree); Content annotationDocTree = writer.getAnnotationDocTreeHeader( currentMember, detailsTree); @@ -154,8 +154,8 @@ detailsTree.add(writer.getAnnotationDoc( annotationDocTree, currentMember == lastMember)); - memberDetailsTree.add(writer.getAnnotationDetails(detailsTree)); } + memberDetailsTree.add(writer.getAnnotationDetails(annotationDetailsTreeHeader, detailsTree)); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -28,6 +28,7 @@ import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.toolkit.ClassWriter; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler; @@ -166,8 +167,7 @@ * @throws DocletException if there is a problem while building the documentation */ protected void buildClassInfo(Content classContentTree) throws DocletException { - Content classInfoTree = writer.getClassInfoTreeHeader(); - + Content classInfoTree = new ContentBuilder(); buildTypeParamInfo(classInfoTree); buildSuperInterfacesInfo(classInfoTree); buildImplementedInterfacesInfo(classInfoTree); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -135,8 +135,9 @@ return; } if (hasMembersToDocument()) { - Content constructorDetailsTree = writer.getConstructorDetailsTreeHeader(typeElement, + Content constructorDetailsTreeHeader = writer.getConstructorDetailsTreeHeader(typeElement, memberDetailsTree); + Content constructorDetailsTree = writer.getMemberTreeHeader(); Element lastElement = constructors.get(constructors.size() - 1); for (Element contructor : constructors) { @@ -152,7 +153,7 @@ currentConstructor == lastElement)); } memberDetailsTree.add( - writer.getConstructorDetails(constructorDetailsTree)); + writer.getConstructorDetails(constructorDetailsTreeHeader, constructorDetailsTree)); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -123,8 +123,9 @@ return; } if (hasMembersToDocument()) { - Content enumConstantsDetailsTree = writer.getEnumConstantsDetailsTreeHeader(typeElement, + Content enumConstantsDetailsTreeHeader = writer.getEnumConstantsDetailsTreeHeader(typeElement, memberDetailsTree); + Content enumConstantsDetailsTree = writer.getMemberTreeHeader(); Element lastElement = enumConstants.get(enumConstants.size() - 1); for (Element enumConstant : enumConstants) { currentElement = (VariableElement)enumConstant; @@ -140,7 +141,7 @@ enumConstantsTree, currentElement == lastElement)); } memberDetailsTree.add( - writer.getEnumConstantsDetails(enumConstantsDetailsTree)); + writer.getEnumConstantsDetails(enumConstantsDetailsTreeHeader, enumConstantsDetailsTree)); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -125,7 +125,8 @@ return; } if (!fields.isEmpty()) { - Content fieldDetailsTree = writer.getFieldDetailsTreeHeader(typeElement, memberDetailsTree); + Content fieldDetailsTreeHeader = writer.getFieldDetailsTreeHeader(typeElement, memberDetailsTree); + Content fieldDetailsTree = writer.getMemberTreeHeader(); Element lastElement = fields.get(fields.size() - 1); for (Element element : fields) { @@ -141,7 +142,7 @@ fieldDocTree, currentElement == lastElement)); } memberDetailsTree.add( - writer.getFieldDetails(fieldDetailsTree)); + writer.getFieldDetails(fieldDetailsTreeHeader, fieldDetailsTree)); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -465,7 +465,7 @@ Content linksTree = writer.getInheritedSummaryLinksTree(); addSummaryFootNote(inheritedClass, inheritedMembers, linksTree, writer); inheritedTree.add(linksTree); - summaryTreeList.add(writer.getMemberTree(inheritedTree)); + summaryTreeList.add(inheritedTree); } } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -126,8 +126,9 @@ return; } if (hasMembersToDocument()) { - Content methodDetailsTree = writer.getMethodDetailsTreeHeader(typeElement, + Content methodDetailsTreeHeader = writer.getMethodDetailsTreeHeader(typeElement, memberDetailsTree); + Content methodDetailsTree = writer.getMemberTreeHeader(); Element lastElement = methods.get(methods.size() - 1); for (Element method : methods) { @@ -142,7 +143,7 @@ methodDetailsTree.add(writer.getMethodDoc( methodDocTree, currentMethod == lastElement)); } - memberDetailsTree.add(writer.getMethodDetails(methodDetailsTree)); + memberDetailsTree.add(writer.getMethodDetails(methodDetailsTreeHeader, methodDetailsTree)); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -163,7 +163,7 @@ buildErrorSummary(summaryContentTree); buildAnnotationTypeSummary(summaryContentTree); - packageContentTree.add(summaryContentTree); + packageContentTree.add(packageWriter.getPackageSummary(summaryContentTree)); } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -125,8 +125,9 @@ return; } if (hasMembersToDocument()) { - Content propertyDetailsTree = writer.getPropertyDetailsTreeHeader(typeElement, + Content propertyDetailsTreeHeader = writer.getPropertyDetailsTreeHeader(typeElement, memberDetailsTree); + Content propertyDetailsTree = writer.getMemberTreeHeader(); Element lastElement = properties.get(properties.size() - 1); for (Element property : properties) { currentProperty = (ExecutableElement)property; @@ -141,7 +142,7 @@ propertyDocTree, currentProperty == lastElement)); } memberDetailsTree.add( - writer.getPropertyDetails(propertyDetailsTree)); + writer.getPropertyDetails(propertyDetailsTreeHeader, propertyDetailsTree)); } } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java 2019-04-24 19:25:41.000000000 +0000 @@ -232,7 +232,7 @@ buildSerialUIDInfo(classTree); buildClassContent(classTree); - classSerializedTree.add(classTree); + classSerializedTree.add(writer.getMemberTree(classTree)); } } packageSerializedTree.add(classSerializedTree); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ConstructorWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ConstructorWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ConstructorWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ConstructorWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -99,10 +99,11 @@ /** * Get the constructor details tree. * + * memberDetailsTreeHeader the content tree representing member details header * @param memberDetailsTree the content tree representing member details * @return content tree for the constructor details */ - public Content getConstructorDetails(Content memberDetailsTree); + public Content getConstructorDetails(Content memberDetailsTreeHeader, Content memberDetailsTree); /** * Get the constructor documentation. @@ -119,4 +120,11 @@ * @param foundNonPubConstructor true if we found a non public constructor. */ public void setFoundNonPubConstructor(boolean foundNonPubConstructor); + + /** + * Gets the member header tree. + * + * @return a content tree for the member header + */ + public Content getMemberTreeHeader(); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/EnumConstantWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/EnumConstantWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/EnumConstantWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/EnumConstantWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -102,7 +102,7 @@ * @param memberDetailsTree the content tree representing member details * @return content tree for the enum constant details */ - public Content getEnumConstantsDetails(Content memberDetailsTree); + public Content getEnumConstantsDetails(Content memberDetailsTreeHeader, Content memberDetailsTree); /** * Get the enum constants documentation. @@ -112,4 +112,11 @@ * @return content tree for the enum constants documentation */ public Content getEnumConstants(Content enumConstantsTree, boolean isLastContent); + + /** + * Gets the member header tree. + * + * @return a content tree for the member header + */ + public Content getMemberTreeHeader(); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/FieldWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/FieldWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/FieldWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/FieldWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -100,10 +100,11 @@ /** * Get the field details tree. * + * @param memberDetailsTreeHeader the content tree representing member details tree header * @param memberDetailsTree the content tree representing member details * @return content tree for the field details */ - public Content getFieldDetails(Content memberDetailsTree); + public Content getFieldDetails(Content memberDetailsTreeHeader, Content memberDetailsTree); /** * Get the field documentation. @@ -113,4 +114,11 @@ * @return content tree for the field documentation */ public Content getFieldDoc(Content fieldDocTree, boolean isLastContent); + + /** + * Gets the member header tree. + * + * @return a content tree for the member header + */ + public Content getMemberTreeHeader(); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MethodWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MethodWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MethodWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MethodWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -101,10 +101,11 @@ /** * Get the method details tree. * + * @param methodDetailsTreeHeader the content tree representing method details header * @param methodDetailsTree the content tree representing method details * @return content tree for the method details */ - public Content getMethodDetails(Content methodDetailsTree); + public Content getMethodDetails(Content methodDetailsTreeHeader, Content methodDetailsTree); /** * Get the method documentation. @@ -114,4 +115,11 @@ * @return content tree for the method documentation */ public Content getMethodDoc(Content methodDocTree, boolean isLastContent); + + /** + * Gets the member header tree. + * + * @return a content tree for the member header + */ + public Content getMemberTreeHeader(); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PackageSummaryWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PackageSummaryWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PackageSummaryWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PackageSummaryWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -163,4 +163,11 @@ */ public abstract void printDocument(Content contentTree) throws DocFileIOException; + /** + * Gets the package summary tree. + * @param summaryContentTree the content tree representing the package summary + * @return a content tree for the package summary + */ + public abstract Content getPackageSummary(Content summaryContentTree); + } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -99,10 +99,11 @@ /** * Get the property details tree. * + * @param memberDetailsTreeHeader the content tree representing member details header * @param memberDetailsTree the content tree representing member details * @return content tree for the property details */ - public Content getPropertyDetails(Content memberDetailsTree); + public Content getPropertyDetails(Content memberDetailsTreeHeader, Content memberDetailsTree); /** * Get the property documentation. @@ -112,4 +113,11 @@ * @return content tree for the property documentation */ public Content getPropertyDoc(Content propertyDocTree, boolean isLastContent); + + /** + * Gets the member header tree. + * + * @return a content tree for the member header + */ + public Content getMemberTreeHeader(); } diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js 2019-04-24 19:25:41.000000000 +0000 @@ -29,11 +29,11 @@ var memberSearchIndex; var tagSearchIndex; function loadScripts(doc, tag) { - createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); - createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + createElem(doc, tag, 'script-dir/jszip/dist/jszip.js'); + createElem(doc, tag, 'script-dir/jszip-utils/dist/jszip-utils.js'); if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || window.navigator.userAgent.indexOf('Edge/') > 0) { - createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + createElem(doc, tag, 'script-dir/jszip-utils/dist/jszip-utils-ie.js'); } createElem(doc, tag, 'search.js'); diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css 2019-04-24 19:25:41.000000000 +0000 @@ -207,18 +207,13 @@ padding: 5px 6px; text-transform:uppercase; } -ul.navListSearch { +.subNav .navListSearch { float:right; margin:0 0 0 0; - padding:0; -} -ul.navListSearch li { - list-style:none; - float:right; - padding: 5px 6px; - text-transform:uppercase; + padding:5px 6px; + clear:none; } -ul.navListSearch li label { +.navListSearch label { position:relative; right:-16px; } @@ -304,7 +299,8 @@ margin:15px 0; } body.class-declaration .summary h3, -body.class-declaration .details h3 { +body.class-declaration .details h3, +body.class-declaration .summary .inheritedList h2 { background-color:#dee3e9; border:1px solid #d0d9e0; margin:0 0 6px -8px; @@ -385,32 +381,11 @@ margin:10px 0 10px 0; padding:0; } -ul.blockList li.blockList, ul.blockListLast li.blockList { +ul.blockList li.blockList, ul.blockList li.blockListLast { list-style:none; margin-bottom:15px; line-height:1.4; } -ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { - padding:0px 20px 5px 10px; - border:1px solid #ededed; - background-color:#f8f8f8; -} -ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { - padding:0 0 5px 8px; - background-color:#ffffff; - border:none; -} -ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { - margin-left:0; - padding-left:0; - padding-bottom:15px; - border:none; -} -ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { - list-style:none; - border-bottom:none; - padding-bottom:0; -} table tr td dl, table tr td dl dt, table tr td dl dd { margin-top:0; margin-bottom:1px; @@ -787,6 +762,23 @@ .methodSignature { white-space:normal; } +.inheritedList { + margin: 10px 0 10px 0; +} +section.description { + line-height: 1.4; +} +.summary section[class$="Summary"], .details section[class$="Details"], +.classUses .detail, .serializedClassDetails { + padding: 0px 20px 5px 10px; + border: 1px solid #ededed; + background-color: #f8f8f8; +} +.inheritedList, section[class$="Details"] .detail { + padding:0 0 5px 8px; + background-color:#ffffff; + border:none; +} /* * Styles for user-provided tables. diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/SerializedFormWriter.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/SerializedFormWriter.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/SerializedFormWriter.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/SerializedFormWriter.java 2019-04-24 19:25:41.000000000 +0000 @@ -163,6 +163,14 @@ public abstract void printDocument(Content serializedTree) throws DocFileIOException; /** + * Gets the member tree. + * + * @param contentTree the tree used to generate the complete member tree + * @return a content tree for the member + */ + public Content getMemberTree(Content contentTree); + + /** * Write the serialized form for a given field. */ public interface SerialFieldWriter { diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java 2019-04-24 19:25:41.000000000 +0000 @@ -39,14 +39,12 @@ * */ public class DocPaths { - private final boolean useModuleDirectories; private final String moduleSeparator; private final Utils utils; - public DocPaths(Utils utils, boolean useModuleDirectories) { + public DocPaths(Utils utils) { this.utils = utils; - this.useModuleDirectories = useModuleDirectories; - moduleSeparator = useModuleDirectories ? "/module-" : "-"; + moduleSeparator = "/module-"; } public static final DocPath DOT_DOT = DocPath.create(".."); @@ -239,12 +237,8 @@ } DocPath pkgPath = DocPath.create(pkgElement.getQualifiedName().toString().replace('.', '/')); - if (useModuleDirectories) { - ModuleElement mdle = (ModuleElement) pkgElement.getEnclosingElement(); - return forModule(mdle).resolve(pkgPath); - } else { - return pkgPath; - } + ModuleElement mdle = (ModuleElement) pkgElement.getEnclosingElement(); + return forModule(mdle).resolve(pkgPath); } /** diff -Nru openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java --- openjdk-13-13~17/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java 2019-04-24 19:25:41.000000000 +0000 @@ -402,7 +402,7 @@ moduleItems.put(moduleName, item); } else { DocPath pkgPath = DocPath.create(elemname.replace('.', '/')); - if (configuration.useModuleDirectories && moduleName != null) { + if (moduleName != null) { elempath = elempath.resolve(DocPath.create(moduleName).resolve(pkgPath)); } else { elempath = elempath.resolve(pkgPath); diff -Nru openjdk-13-13~17/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java openjdk-13-13~18/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java --- openjdk-13-13~17/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java 2019-04-24 19:25:41.000000000 +0000 @@ -599,11 +599,11 @@ throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); } - // Returns an output SeekableByteChannel for either // (1) writing the contents of a new entry, if the entry doesn't exit, or // (2) updating/replacing the contents of an existing entry. - // Note: The content is not compressed. + // Note: The content of the channel is not compressed until the + // channel is closed private class EntryOutputChannel extends ByteArrayChannel { Entry e; @@ -622,19 +622,19 @@ @Override public void close() throws IOException { - e.bytes = toByteArray(); - e.size = e.bytes.length; - e.crc = -1; + // will update the entry + try (OutputStream os = getOutputStream(e)) { + os.write(toByteArray()); + } super.close(); - update(e); } } - private int getCompressMethod(FileAttribute... attrs) { + private int getCompressMethod() { return defaultMethod; } - // Returns a Writable/ReadByteChannel for now. Might consdier to use + // Returns a Writable/ReadByteChannel for now. Might consider to use // newFileChannel() instead, which dump the entry data into a regular // file on the default file system and create a FileChannel on top of // it. @@ -647,10 +647,9 @@ if (options.contains(StandardOpenOption.WRITE) || options.contains(StandardOpenOption.APPEND)) { checkWritable(); - beginRead(); // only need a readlock, the "update()" will obtain - // thewritelock when the channel is closed + beginRead(); // only need a read lock, the "update()" will obtain + // the write lock when the channel is closed try { - ensureOpen(); Entry e = getEntry(path); if (e != null) { if (e.isDir() || options.contains(CREATE_NEW)) @@ -675,8 +674,7 @@ throw new NoSuchFileException(getString(path)); checkParents(path); return new EntryOutputChannel( - new Entry(path, Entry.NEW, false, getCompressMethod(attrs))); - + new Entry(path, Entry.NEW, false, getCompressMethod())); } finally { endRead(); } @@ -743,7 +741,7 @@ final Entry u = isFCH ? e : new Entry(path, tmpfile, Entry.FILECH); if (forWrite) { u.flag = FLAG_DATADESCR; - u.method = getCompressMethod(attrs); + u.method = getCompressMethod(); } // is there a better way to hook into the FileChannel's close method? return new FileChannel() { @@ -844,7 +842,11 @@ // the outstanding input streams that need to be closed private Set streams = - Collections.synchronizedSet(new HashSet()); + Collections.synchronizedSet(new HashSet<>()); + + // the ex-channel and ex-path that need to close when their outstanding + // input streams are all closed by the obtainers. + private Set exChClosers = new HashSet<>(); private Set tmppaths = Collections.synchronizedSet(new HashSet()); private Path getTempPathForEntry(byte[] path) throws IOException { @@ -1202,25 +1204,20 @@ return written; } - private long writeEntry(Entry e, OutputStream os, byte[] buf) + private long writeEntry(Entry e, OutputStream os) throws IOException { if (e.bytes == null && e.file == null) // dir, 0-length data return 0; long written = 0; - try (OutputStream os2 = e.method == METHOD_STORED ? - new EntryOutputStreamCRC32(e, os) : new EntryOutputStreamDef(e, os)) { - if (e.bytes != null) { // in-memory - os2.write(e.bytes, 0, e.bytes.length); - } else if (e.file != null) { // tmp file - if (e.type == Entry.NEW || e.type == Entry.FILECH) { - try (InputStream is = Files.newInputStream(e.file)) { - is.transferTo(os2); - } - } - Files.delete(e.file); - tmppaths.remove(e.file); + if (e.crc != 0 && e.csize > 0) { + // pre-compressed entry, write directly to output stream + writeTo(e, os); + } else { + try (OutputStream os2 = (e.method == METHOD_STORED) ? + new EntryOutputStreamCRC32(e, os) : new EntryOutputStreamDef(e, os)) { + writeTo(e, os2); } } written += e.csize; @@ -1230,18 +1227,38 @@ return written; } + private void writeTo(Entry e, OutputStream os) throws IOException { + if (e.bytes != null) { + os.write(e.bytes, 0, e.bytes.length); + } else if (e.file != null) { + if (e.type == Entry.NEW || e.type == Entry.FILECH) { + try (InputStream is = Files.newInputStream(e.file)) { + is.transferTo(os); + } + } + Files.delete(e.file); + tmppaths.remove(e.file); + } + } + // sync the zip file system, if there is any udpate private void sync() throws IOException { - + // check ex-closer + if (!exChClosers.isEmpty()) { + for (ExistingChannelCloser ecc : exChClosers) { + if (ecc.closeAndDeleteIfDone()) { + exChClosers.remove(ecc); + } + } + } if (!hasUpdate) return; Path tmpFile = createTempFileInSameDirectoryAs(zfpath); - try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE))) - { + try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE))) { ArrayList elist = new ArrayList<>(inodes.size()); long written = 0; - byte[] buf = new byte[8192]; - Entry e = null; + byte[] buf = null; + Entry e; // write loc for (IndexNode inode : inodes.values()) { @@ -1254,11 +1271,13 @@ // LOC in new file and simply copy the rest (data and // ext) without enflating/deflating from the old zip // file LOC entry. + if (buf == null) + buf = new byte[8192]; written += copyLOCEntry(e, true, os, written, buf); } else { // NEW, FILECH or CEN e.locoff = written; written += e.writeLOC(os); // write loc header - written += writeEntry(e, os, buf); + written += writeEntry(e, os); } elist.add(e); } catch (IOException x) { @@ -1274,6 +1293,8 @@ } e = Entry.readCEN(this, inode); try { + if (buf == null) + buf = new byte[8192]; written += copyLOCEntry(e, false, os, written, buf); elist.add(e); } catch (IOException x) { @@ -1291,9 +1312,23 @@ end.cenlen = written - end.cenoff; end.write(os, written, forceEnd64); } + if (!streams.isEmpty()) { + // + // There are outstanding input streams open on existing "ch", + // so, don't close the "cha" and delete the "file for now, let + // the "ex-channel-closer" to handle them + Path path = createTempFileInSameDirectoryAs(zfpath); + ExistingChannelCloser ecc = new ExistingChannelCloser(path, + ch, + streams); + Files.move(zfpath, path, REPLACE_EXISTING); + exChClosers.add(ecc); + streams = Collections.synchronizedSet(new HashSet<>()); + } else { + ch.close(); + Files.delete(zfpath); + } - ch.close(); - Files.delete(zfpath); Files.move(tmpFile, zfpath, REPLACE_EXISTING); hasUpdate = false; // clear } @@ -1351,11 +1386,15 @@ } else { os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192); } - return new EntryOutputStream(e, os); + if (e.method == METHOD_DEFLATED) { + return new DeflatingEntryOutputStream(e, os); + } else { + return new EntryOutputStream(e, os); + } } private class EntryOutputStream extends FilterOutputStream { - private Entry e; + private final Entry e; private long written; private boolean isClosed; @@ -1392,13 +1431,56 @@ } } + // Output stream returned when writing "deflated" entries into memory, + // to enable eager (possibly parallel) deflation and reduce memory required. + private class DeflatingEntryOutputStream extends DeflaterOutputStream { + private final CRC32 crc; + private final Entry e; + private boolean isClosed; + + DeflatingEntryOutputStream(Entry e, OutputStream os) throws IOException { + super(os, getDeflater()); + this.e = Objects.requireNonNull(e, "Zip entry is null"); + this.crc = new CRC32(); + } + + @Override + public synchronized void write(int b) throws IOException { + super.write(b); + crc.update(b); + } + + @Override + public synchronized void write(byte b[], int off, int len) + throws IOException { + super.write(b, off, len); + crc.update(b, off, len); + } + + @Override + public synchronized void close() throws IOException { + if (isClosed) + return; + isClosed = true; + finish(); + e.size = def.getBytesRead(); + e.csize = def.getBytesWritten(); + e.crc = crc.getValue(); + if (out instanceof ByteArrayOutputStream) + e.bytes = ((ByteArrayOutputStream)out).toByteArray(); + super.close(); + update(e); + releaseDeflater(def); + } + } + // Wrapper output stream class to write out a "stored" entry. // (1) this class does not close the underlying out stream when // being closed. // (2) no need to be "synchronized", only used by sync() private class EntryOutputStreamCRC32 extends FilterOutputStream { - private Entry e; - private CRC32 crc; + private final CRC32 crc; + private final Entry e; private long written; private boolean isClosed; @@ -1438,8 +1520,8 @@ // being closed. // (2) no need to be "synchronized", only used by sync() private class EntryOutputStreamDef extends DeflaterOutputStream { - private CRC32 crc; - private Entry e; + private final CRC32 crc; + private final Entry e; private boolean isClosed; EntryOutputStreamDef(Entry e, OutputStream os) throws IOException { @@ -1471,14 +1553,12 @@ private InputStream getInputStream(Entry e) throws IOException { - InputStream eis = null; - + InputStream eis; if (e.type == Entry.NEW) { - // now bytes & file is uncompressed. if (e.bytes != null) - return new ByteArrayInputStream(e.bytes); + eis = new ByteArrayInputStream(e.bytes); else if (e.file != null) - return Files.newInputStream(e.file); + eis = Files.newInputStream(e.file); else throw new ZipException("update entry data is missing"); } else if (e.type == Entry.FILECH) { @@ -1579,7 +1659,7 @@ len = (int) rem; } // readFullyAt() - long n = 0; + long n; ByteBuffer bb = ByteBuffer.wrap(b); bb.position(off); bb.limit(off + len); @@ -1905,7 +1985,7 @@ this.type = type; } - Entry (Entry e, int type) { + Entry(Entry e, int type) { name(e.name); this.isdir = e.isdir; this.version = e.version; @@ -1928,7 +2008,7 @@ this.type = type; } - Entry (byte[] name, Path file, int type) { + Entry(byte[] name, Path file, int type) { this(name, type, false, METHOD_STORED); this.file = file; } @@ -2424,6 +2504,36 @@ } } + private static class ExistingChannelCloser { + private final Path path; + private final SeekableByteChannel ch; + private final Set streams; + ExistingChannelCloser(Path path, + SeekableByteChannel ch, + Set streams) { + this.path = path; + this.ch = ch; + this.streams = streams; + } + + /** + * If there are no more outstanding streams, close the channel and + * delete the backing file + * + * @return true if we're done and closed the backing file, + * otherwise false + * @throws IOException + */ + public boolean closeAndDeleteIfDone() throws IOException { + if (streams.isEmpty()) { + ch.close(); + Files.delete(path); + return true; + } + return false; + } + } + // ZIP directory has two issues: // (1) ZIP spec does not require the ZIP file to include // directory entry diff -Nru openjdk-13-13~17/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java openjdk-13-13~18/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java --- openjdk-13-13~17/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,7 +104,7 @@ if (filesystems.containsKey(realPath)) throw new FileSystemAlreadyExistsException(); } - ZipFileSystem zipfs = null; + ZipFileSystem zipfs; try { if (env.containsKey("multi-release")) { zipfs = new JarFileSystem(this, path, env); @@ -131,13 +131,13 @@ throws IOException { ensureFile(path); - try { - ZipFileSystem zipfs; - if (env.containsKey("multi-release")) { - zipfs = new JarFileSystem(this, path, env); - } else { - zipfs = new ZipFileSystem(this, path, env); - } + try { + ZipFileSystem zipfs; + if (env.containsKey("multi-release")) { + zipfs = new JarFileSystem(this, path, env); + } else { + zipfs = new ZipFileSystem(this, path, env); + } return zipfs; } catch (ZipException ze) { String pname = path.toString(); diff -Nru openjdk-13-13~17/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java openjdk-13-13~18/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java --- openjdk-13-13~17/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java 2019-04-24 19:25:41.000000000 +0000 @@ -676,7 +676,7 @@ @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { private int i = 0; @Override @@ -746,8 +746,8 @@ void setAttribute(String attribute, Object value, LinkOption... options) throws IOException { - String type = null; - String attr = null; + String type; + String attr; int colonPos = attribute.indexOf(':'); if (colonPos == -1) { type = "basic"; @@ -772,8 +772,8 @@ throws IOException { - String view = null; - String attrs = null; + String view; + String attrs; int colonPos = attributes.indexOf(':'); if (colonPos == -1) { view = "basic"; diff -Nru openjdk-13-13~17/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java openjdk-13-13~18/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java --- openjdk-13-13~17/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -270,8 +270,7 @@ // Some tests rely on MX_SUBPROCESS_COMMAND_FILE env variable which contains // name of the file with java executable and java args used to launch the current process. Path cmdFile = Files.createTempFile(Path.of(""), "mx_subprocess_", ".cmd"); - Files.writeString(cmdFile, JDKToolFinder.getJDKTool("java") + System.lineSeparator()); - Files.write(cmdFile, javaFlags, StandardOpenOption.APPEND); + Files.write(cmdFile, javaPB.command()); javaPB.environment().put("MX_SUBPROCESS_COMMAND_FILE", cmdFile.toAbsolutePath().toString()); System.out.println("INFO: run command: " + String.join(" ", javaPB.command())); diff -Nru openjdk-13-13~17/test/hotspot/jtreg/compiler/graalunit/HotspotAarch64Test.java openjdk-13-13~18/test/hotspot/jtreg/compiler/graalunit/HotspotAarch64Test.java --- openjdk-13-13~17/test/hotspot/jtreg/compiler/graalunit/HotspotAarch64Test.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/compiler/graalunit/HotspotAarch64Test.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary + * @requires vm.opt.final.EnableJVMCI == true + * + * @modules jdk.internal.vm.compiler + * + * @library /test/lib /compiler/graalunit / + * + * @build compiler.graalunit.common.GraalUnitTestLauncher + * + * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt + * + * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.aarch64.test -exclude ExcludeList.txt + */ + +/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */ diff -Nru openjdk-13-13~17/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt openjdk-13-13~18/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt --- openjdk-13-13~17/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt 2019-04-24 19:25:41.000000000 +0000 @@ -10,6 +10,7 @@ EA9 org.graalvm.compiler.core.jdk9.test.ea Debug org.graalvm.compiler.debug.test Graph org.graalvm.compiler.graph.test @requires vm.graal.enabled +HotspotAarch64 org.graalvm.compiler.hotspot.aarch64.test HotspotAmd64 org.graalvm.compiler.hotspot.amd64.test HotspotJdk9 org.graalvm.compiler.hotspot.jdk9.test HotspotSparc org.graalvm.compiler.hotspot.sparc.test @requires vm.simpleArch == "sparcv9" diff -Nru openjdk-13-13~17/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java openjdk-13-13~18/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java --- openjdk-13-13~17/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java 2019-04-24 19:25:41.000000000 +0000 @@ -42,7 +42,8 @@ public static void main(String args[]) throws Exception { if (args.length == 0) { // Spawn new VM instance to execute test - String[] flags = {"-XX:-BytecodeVerificationRemote", + String[] flags = {"-XX:+UnlockDiagnosticVMOptions", + "-XX:-BytecodeVerificationRemote", "-XX:-BytecodeVerificationLocal", "-XX:-TieredCompilation", "-XX:CompileCommand=dontinline,compiler/linkage/OSRWithBadOperandStack.m*", diff -Nru openjdk-13-13~17/test/hotspot/jtreg/runtime/appcds/VerifierTest.java openjdk-13-13~18/test/hotspot/jtreg/runtime/appcds/VerifierTest.java --- openjdk-13-13~17/test/hotspot/jtreg/runtime/appcds/VerifierTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/runtime/appcds/VerifierTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -38,7 +38,7 @@ // Test verification settings for dumping & runtime static final String VFY_ALL = "-Xverify:all"; static final String VFY_REMOTE = "-Xverify:remote"; // default - static final String VFY_NONE = "-XX:-BytecodeVerificationRemote, -XX:-BytecodeVerificationLocal"; + static final String VFY_NONE = "-XX:+UnlockDiagnosticVMOptions, -XX:-BytecodeVerificationRemote, -XX:-BytecodeVerificationLocal"; static final String ERR = "ERROR: class VerifierTestC was loaded unexpectedly"; @@ -188,18 +188,20 @@ if (!dump_setting.equals(prev_dump_setting)) { String dump_arg1; String dump_arg2; + String dump_arg3; // Need to break this into two separate arguments. if (dump_setting.equals(VFY_NONE)) { - dump_arg1 = "-XX:-BytecodeVerificationRemote"; - dump_arg2 = "-XX:-BytecodeVerificationLocal"; + dump_arg1 = "-XX:+UnlockDiagnosticVMOptions"; + dump_arg2 = "-XX:-BytecodeVerificationRemote"; + dump_arg3 = "-XX:-BytecodeVerificationLocal"; } else { // Redundant args should be harmless. - dump_arg1 = dump_arg2 = dump_setting; + dump_arg1 = dump_arg2 = dump_arg3 = dump_setting; } OutputAnalyzer dumpOutput = TestCommon.dump( jar, dump_list, dump_arg1, dump_arg2, - CDS_LOGGING, + dump_arg3, CDS_LOGGING, // FIXME: the following options are for working around a GC // issue - assert failure when dumping archive with the -Xverify:all "-Xms256m", @@ -211,15 +213,17 @@ } String runtime_arg1; String runtime_arg2; + String runtime_arg3; if (runtime_setting.equals(VFY_NONE)) { - runtime_arg1 = "-XX:-BytecodeVerificationRemote"; - runtime_arg2 = "-XX:-BytecodeVerificationLocal"; + runtime_arg1 = "-XX:+UnlockDiagnosticVMOptions"; + runtime_arg2 = "-XX:-BytecodeVerificationRemote"; + runtime_arg3 = "-XX:-BytecodeVerificationLocal"; } else { // Redundant args should be harmless. - runtime_arg1 = runtime_arg2 = runtime_setting; + runtime_arg1 = runtime_arg2 = runtime_arg3 = runtime_setting; } TestCommon.run("-cp", jar, - runtime_arg1, runtime_arg2, + runtime_arg1, runtime_arg2, runtime_arg3, "VerifierTest0") .ifNoMappingFailure(output -> checkRuntimeOutput(output, expected_output_str)); prev_dump_setting = dump_setting; @@ -266,16 +270,18 @@ if (!dump_setting.equals(prev_dump_setting)) { String dump_arg1; String dump_arg2; + String dump_arg3; if (dump_setting.equals(VFY_NONE)) { - dump_arg1 = "-XX:-BytecodeVerificationRemote"; - dump_arg2 = "-XX:-BytecodeVerificationLocal"; + dump_arg1 = "-XX:+UnlockDiagnosticVMOptions"; + dump_arg2 = "-XX:-BytecodeVerificationRemote"; + dump_arg3 = "-XX:-BytecodeVerificationLocal"; } else { // Redundant args should be harmless. - dump_arg1 = dump_arg2 = dump_setting; + dump_arg1 = dump_arg2 = dump_arg3 = dump_setting; } OutputAnalyzer dumpOutput = TestCommon.dump( jar, appClasses, dump_arg1, dump_arg2, - CDS_LOGGING, + dump_arg3, CDS_LOGGING, // FIXME: the following options are for working around a GC // issue - assert failure when dumping archive with the -Xverify:all "-Xms256m", @@ -287,15 +293,17 @@ } String runtime_arg1; String runtime_arg2; + String runtime_arg3; if (runtime_setting.equals(VFY_NONE)) { - runtime_arg1 = "-XX:-BytecodeVerificationRemote"; - runtime_arg2 = "-XX:-BytecodeVerificationLocal"; + runtime_arg1 = "-XX:+UnlockDiagnosticVMOptions"; + runtime_arg2 = "-XX:-BytecodeVerificationRemote"; + runtime_arg3 = "-XX:-BytecodeVerificationLocal"; } else { // Redundant args should be harmless. - runtime_arg1 = runtime_arg2 = runtime_setting; + runtime_arg1 = runtime_arg2 = runtime_arg3 = runtime_setting; } TestCommon.run("-cp", jar, - runtime_arg1, runtime_arg2, + runtime_arg1, runtime_arg2, runtime_arg3, "Hi") .ifNoMappingFailure(output -> checkRuntimeOutput(output, expected_output_str)); prev_dump_setting = dump_setting; diff -Nru openjdk-13-13~17/test/hotspot/jtreg/runtime/clone/invokevirtual/HasLocalClone.jasm openjdk-13-13~18/test/hotspot/jtreg/runtime/clone/invokevirtual/HasLocalClone.jasm --- openjdk-13-13~17/test/hotspot/jtreg/runtime/clone/invokevirtual/HasLocalClone.jasm 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/runtime/clone/invokevirtual/HasLocalClone.jasm 2019-04-24 19:25:41.000000000 +0000 @@ -28,7 +28,7 @@ * @summary Check that invokevirtual of clone() finds the clone() method that * is local to the calling class. * @compile DefMethClone.jasm SuperClass.jasm I1.java HasLocalClone.jasm - * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal HasLocalClone + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal HasLocalClone */ // The below .jasm code implements the following java code: diff -Nru openjdk-13-13~17/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalCloneAbstr.jasm openjdk-13-13~18/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalCloneAbstr.jasm --- openjdk-13-13~17/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalCloneAbstr.jasm 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalCloneAbstr.jasm 2019-04-24 19:25:41.000000000 +0000 @@ -28,7 +28,7 @@ * @summary Check that invokevirtual of clone() calls java.lang.Object.clone() * even if a superinterface has an abstract method named clone(). * @compile DefMethClone.jasm SuperClass.jasm I1Abstr.java NoLocalCloneAbstr.jasm - * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal NoLocalCloneAbstr + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal NoLocalCloneAbstr */ // The below .jasm code implements the following java code: diff -Nru openjdk-13-13~17/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalClone.jasm openjdk-13-13~18/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalClone.jasm --- openjdk-13-13~17/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalClone.jasm 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalClone.jasm 2019-04-24 19:25:41.000000000 +0000 @@ -28,7 +28,7 @@ * @summary Check that invokevirtual of clone() calls java.lang.Object.clone() * even if a superinterface has a default method named clone(). * @compile DefMethClone.jasm SuperClass.jasm I1.java NoLocalClone.jasm - * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal NoLocalClone + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal NoLocalClone */ // The below .jasm code implements the following java code: diff -Nru openjdk-13-13~17/test/hotspot/jtreg/runtime/lambda-features/TestStaticandInstance.java openjdk-13-13~18/test/hotspot/jtreg/runtime/lambda-features/TestStaticandInstance.java --- openjdk-13-13~17/test/hotspot/jtreg/runtime/lambda-features/TestStaticandInstance.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/runtime/lambda-features/TestStaticandInstance.java 2019-04-24 19:25:41.000000000 +0000 @@ -26,7 +26,7 @@ * @bug 8087342 * @summary Test linkresolver search static, instance and overpass duplicates * @modules java.base/jdk.internal.org.objectweb.asm - * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal TestStaticandInstance + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal TestStaticandInstance */ diff -Nru openjdk-13-13~17/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java openjdk-13-13~18/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java --- openjdk-13-13~17/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java 2019-04-24 19:25:41.000000000 +0000 @@ -33,10 +33,15 @@ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MemberNameLeak */ +import java.io.*; +import java.nio.file.*; import java.lang.invoke.*; import java.lang.reflect.*; +import java.text.*; +import java.util.*; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.Utils; import sun.hotspot.WhiteBox; import sun.hotspot.code.Compiler; import sun.hotspot.gc.GC; @@ -47,6 +52,7 @@ // The size of the ResolvedMethodTable is 1024. 2000 entries // is enough to trigger a grow/cleaning of the table after a GC. private static int methodCount = 2000; + public static ArrayList keepAlive; static class Leak { public void callMe() { @@ -56,6 +62,8 @@ Leak leak = new Leak(); WhiteBox wb = WhiteBox.getWhiteBox(); + keepAlive = new ArrayList<>(methodCount); + ClassWithManyMethodsClassLoader classLoader = new ClassWithManyMethodsClassLoader(); Class clazz = classLoader.create(className, methodPrefix, methodCount); @@ -74,14 +82,20 @@ MethodHandle mh1 = lookup.findSpecial(clazz, methodName, mt, clazz); mh1.invoke(o); + + keepAlive.add(mh1); } long after = wb.resolvedMethodItemsCount(); + System.out.println("wb.resolvedMethodItemsCount() after setup: " + after); + if (after == before) { throw new RuntimeException("Too few resolved methods"); } + keepAlive = null; + // Wait until ServiceThread cleans ResolvedMethod table int cnt = 0; while (true) { @@ -99,27 +113,48 @@ } } + private static Path createGcLogPath(String prefix) throws IOException { + Path gcLog = Utils.createTempFile(prefix, "log"); + Files.delete(gcLog); + return gcLog; + } + + private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + public static void test(GC gc, boolean doConcurrent) throws Throwable { - System.err.println("test(" + gc + ", " + doConcurrent + ")"); + Path gcLogPath = createGcLogPath("gc." + gc + "." + doConcurrent); + System.err.println("test(" + gc + ", " + doConcurrent + ")" + " " + dateFormat.format(new Date())); // Run this Leak class with logging ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:membername+table=trace", + "-Xlog:membername+table=trace,gc+verify=debug,gc:" + gcLogPath + ":time,utctime,uptime,pid,level,tags", "-XX:+UnlockExperimentalVMOptions", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "-Xbootclasspath/a:.", + "-XX:+VerifyBeforeGC", + "-XX:+VerifyAfterGC", doConcurrent ? "-XX:+ExplicitGCInvokesConcurrent" : "-XX:-ExplicitGCInvokesConcurrent", "-XX:+ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", "-XX:+Use" + gc + "GC", Leak.class.getName()); + + // Check process OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.outputTo(System.out); + output.errorTo(System.err); + output.shouldHaveExitValue(0); + + // Check gc log file + OutputAnalyzer gcLogOutput = new OutputAnalyzer(gcLogPath); + // Hardcoded names for classes generated by GeneratedClassLoader String descriptor = className + "." + methodPrefix + "0()V"; - output.shouldContain("ResolvedMethod entry added for " + descriptor); - output.shouldContain("ResolvedMethod entry found for " + descriptor); - output.shouldContain("ResolvedMethod entry removed"); - output.shouldHaveExitValue(0); + gcLogOutput.shouldContain("ResolvedMethod entry added for " + descriptor); + gcLogOutput.shouldContain("ResolvedMethod entry found for " + descriptor); + gcLogOutput.shouldContain("ResolvedMethod entry removed"); + + System.err.println("test(" + gc + ", " + doConcurrent + ")" + " done " + dateFormat.format(new Date())); } private static boolean supportsSTW(GC gc) { diff -Nru openjdk-13-13~17/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestInvokeErrors.java openjdk-13-13~18/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestInvokeErrors.java --- openjdk-13-13~17/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestInvokeErrors.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestInvokeErrors.java 2019-04-24 19:25:41.000000000 +0000 @@ -32,7 +32,7 @@ * MissingMethodWithSuper.jcod * MissingNestHost.jcod * @run main TestInvokeErrors true - * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal TestInvokeErrors false + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal TestInvokeErrors false */ public class TestInvokeErrors { diff -Nru openjdk-13-13~17/test/hotspot/jtreg/runtime/verifier/TestSigParse.java openjdk-13-13~18/test/hotspot/jtreg/runtime/verifier/TestSigParse.java --- openjdk-13-13~17/test/hotspot/jtreg/runtime/verifier/TestSigParse.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/runtime/verifier/TestSigParse.java 2019-04-24 19:25:41.000000000 +0000 @@ -27,7 +27,7 @@ * @summary Test that signatures are properly parsed when verification of local * classes is requested but verification of remote classes is not. * @compile BadSignatures.jcod - * @run main/othervm -XX:+BytecodeVerificationLocal -XX:-BytecodeVerificationRemote TestSigParse + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+BytecodeVerificationLocal -XX:-BytecodeVerificationRemote TestSigParse */ public class TestSigParse { diff -Nru openjdk-13-13~17/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAddLambdaExpression.java openjdk-13-13~18/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAddLambdaExpression.java --- openjdk-13-13~17/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAddLambdaExpression.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAddLambdaExpression.java 2019-04-24 19:25:41.000000000 +0000 @@ -31,7 +31,7 @@ * java.instrument * jdk.jartool/sun.tools.jar * @run main RedefineClassHelper - * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineAddLambdaExpression + * @run main/othervm -javaagent:redefineagent.jar -XX:+AllowRedefinitionToAddDeleteMethods -Xlog:redefine+class*=trace RedefineAddLambdaExpression */ interface MathOperation { diff -Nru openjdk-13-13~17/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDeleteJmethod.java openjdk-13-13~18/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDeleteJmethod.java --- openjdk-13-13~17/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDeleteJmethod.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDeleteJmethod.java 2019-04-24 19:25:41.000000000 +0000 @@ -31,7 +31,7 @@ * java.instrument * jdk.jartool/sun.tools.jar * @run main RedefineClassHelper - * @run main/native/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineDeleteJmethod + * @run main/native/othervm -javaagent:redefineagent.jar -XX:+AllowRedefinitionToAddDeleteMethods -Xlog:redefine+class*=trace RedefineDeleteJmethod */ class B { diff -Nru openjdk-13-13~17/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSubtractLambdaExpression.java openjdk-13-13~18/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSubtractLambdaExpression.java --- openjdk-13-13~17/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSubtractLambdaExpression.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSubtractLambdaExpression.java 2019-04-24 19:25:41.000000000 +0000 @@ -31,7 +31,7 @@ * java.instrument * jdk.jartool/sun.tools.jar * @run main RedefineClassHelper - * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineSubtractLambdaExpression + * @run main/othervm -javaagent:redefineagent.jar -XX:+AllowRedefinitionToAddDeleteMethods -Xlog:redefine+class*=trace RedefineSubtractLambdaExpression */ interface MathOperation { diff -Nru openjdk-13-13~17/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestAddDeleteMethods.java openjdk-13-13~18/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestAddDeleteMethods.java --- openjdk-13-13~17/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestAddDeleteMethods.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestAddDeleteMethods.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8192936 + * @summary RI does not follow the JVMTI RedefineClasses spec; need to disallow adding and deleting methods + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.compiler + * java.instrument + * jdk.jartool/sun.tools.jar + * @run main RedefineClassHelper + * @run main/othervm -javaagent:redefineagent.jar TestAddDeleteMethods + */ + +import static jdk.test.lib.Asserts.assertEquals; + +// package access top-level class to avoid problem with RedefineClassHelper +// and nested types. +class A { + private static void foo() { System.out.println("OLD foo called"); } + private final void finalFoo() { System.out.println("OLD finalFoo called"); } + public void publicFoo() { foo(); finalFoo(); } +} + +public class TestAddDeleteMethods { + static A a; + + public static String newA = + "class A {" + + "private static void foo() { System.out.println(\"NEW foo called\"); }" + + "private final void finalFoo() { System.out.println(\"NEW finalFoo called\"); }" + + "public void publicFoo() { foo(); finalFoo(); }" + + "}"; + + public static String newAddBar = + "class A {" + + "private void bar() { System.out.println(\"NEW bar called\"); }" + + "private static void foo() { System.out.println(\"NEW foo called\"); }" + + "private final void finalFoo() { System.out.println(\"NEW finalFoo called\"); }" + + "public void publicFoo() { foo(); bar(); finalFoo(); }" + + "}"; + + public static String newAddFinalBar = + "class A {" + + "private final void bar() { System.out.println(\"NEW bar called\"); }" + + "private static void foo() { System.out.println(\"NEW foo called\"); }" + + "private final void finalFoo() { System.out.println(\"NEW finalFoo called\"); }" + + "public void publicFoo() { foo(); bar(); finalFoo(); }" + + "}"; + + public static String newAddPublicBar = + "class A {" + + "public void bar() { System.out.println(\"NEW public bar called\"); }" + + "private static void foo() { System.out.println(\"NEW foo called\"); }" + + "private final void finalFoo() { System.out.println(\"NEW finalFoo called\"); }" + + "public void publicFoo() { foo(); bar(); finalFoo(); }" + + "}"; + + public static String newDeleteFoo = + "class A {" + + "private final void finalFoo() { System.out.println(\"NEW finalFoo called\"); }" + + "public void publicFoo() { finalFoo(); }" + + "}"; + + public static String newDeleteFinalFoo = + "class A {" + + "private static void foo() { System.out.println(\"NEW foo called\"); }" + + "public void publicFoo() { foo(); }" + + "}"; + + public static String newDeletePublicFoo = + "class A {" + + "private static void foo() { System.out.println(\"NEW foo called\"); }" + + "private final void finalFoo() { System.out.println(\"NEW finalFoo called\"); }" + + "}"; + + static private final String ExpMsgPrefix = "attempted to "; + static private final String ExpMsgPostfix = " a method"; + + public static void test(String newBytes, String expSuffix) throws Exception { + String expectedMessage = ExpMsgPrefix + expSuffix + ExpMsgPostfix; + + try { + RedefineClassHelper.redefineClass(A.class, newBytes); + a.publicFoo(); + throw new RuntimeException("Failed, expected UOE"); + } catch (UnsupportedOperationException uoe) { + String message = uoe.getMessage(); + System.out.println("Got expected UOE " + message); + if (!message.endsWith(expectedMessage)) { + throw new RuntimeException("Expected UOE error message to end with: " + expectedMessage); + } + } + } + + static { + a = new A(); + } + + public static void main(String[] args) throws Exception { + + a.publicFoo(); + + // Should pass because this only changes bytes of methods. + RedefineClassHelper.redefineClass(A.class, newA); + a.publicFoo(); + + // Add private static bar + test(newAddBar, "add"); + test(newAddFinalBar, "add"); + test(newAddPublicBar, "add"); + test(newDeleteFoo, "delete"); + test(newDeleteFinalFoo, "delete"); + test(newDeletePublicFoo, "delete"); + } +} diff -Nru openjdk-13-13~17/test/hotspot/jtreg/TEST.groups openjdk-13-13~18/test/hotspot/jtreg/TEST.groups --- openjdk-13-13~17/test/hotspot/jtreg/TEST.groups 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/TEST.groups 2019-04-24 19:25:41.000000000 +0000 @@ -438,7 +438,8 @@ # JVMTI tests vmTestbase_nsk_jvmti = \ - vmTestbase/nsk/jvmti + vmTestbase/nsk/jvmti \ + vmTestbase/nsk/share/ExceptionCheckingJniEnv # JDWP tests vmTestbase_nsk_jdwp = \ diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java 2019-04-24 19:25:41.000000000 +0000 @@ -308,10 +308,10 @@ //------------------------------------------------------ testing section log1(" TESTING BEGINS"); + vm.resume(); for (int i = 0; ; i++) { - vm.resume(); breakpointForCommunication(); int instruction = ((IntegerValue) diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include #include #include +#include "ExceptionCheckingJniEnv.hpp" extern "C" { @@ -67,23 +68,15 @@ #define ATTACH002_TARGET_APP_CLASS_NAME "nsk/jvmti/AttachOnDemand/attach002/attach002Target" -int registerNativeMethods(JNIEnv* jni) { +void registerNativeMethods(JNIEnv* jni_env) { + ExceptionCheckingJniEnvPtr jni(jni_env); jclass appClass; JNINativeMethod nativeMethods[] = { { (char*) "agentGotCapabilities", (char*) "()Z", (void*) Java_nsk_jvmti_AttachOnDemand_attach002_attach002Target_agentGotCapabilities } }; jint nativeMethodsNumber = 1; - appClass = jni->FindClass(ATTACH002_TARGET_APP_CLASS_NAME); - if (!NSK_JNI_VERIFY(jni, appClass != NULL)) { - return NSK_FALSE; - } - - if (!NSK_JNI_VERIFY(jni, - (jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber) == 0))) { - return NSK_FALSE; - } - - return NSK_TRUE; + appClass = jni->FindClass(ATTACH002_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL); + jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL); } void JNICALL classLoadHandler( @@ -201,9 +194,7 @@ if (!NSK_VERIFY(jvmti != NULL)) return JNI_ERR; - if (!NSK_VERIFY(registerNativeMethods(jni))) { - return JNI_ERR; - } + registerNativeMethods(jni); memset(&caps, 0, sizeof(caps)); caps.can_generate_all_class_hook_events = 1; diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/libattach002Agent00.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/libattach002Agent00.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/libattach002Agent00.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/libattach002Agent00.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include #include #include +#include "ExceptionCheckingJniEnv.hpp" extern "C" { @@ -87,24 +88,16 @@ */ } -int registerNativeMethods(JNIEnv* jni) { +void registerNativeMethods(JNIEnv* jni_env) { + ExceptionCheckingJniEnvPtr jni(jni_env); jclass appClass; JNINativeMethod nativeMethods[] = { { (char*) "setTagFor", (char*) "(Ljava/lang/Object;)Z", (void*) Java_nsk_jvmti_AttachOnDemand_attach021_attach021Target_setTagFor }, { (char*) "shutdownAgent", (char*) "()V", (void*) Java_nsk_jvmti_AttachOnDemand_attach021_attach021Target_shutdownAgent } }; jint nativeMethodsNumber = 2; - appClass = jni->FindClass(ATTACH021_TARGET_APP_CLASS_NAME); - if (!NSK_JNI_VERIFY(jni, appClass != NULL)) { - return NSK_FALSE; - } - - if (!NSK_JNI_VERIFY(jni, - (jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber) == 0))) { - return NSK_FALSE; - } - - return NSK_TRUE; + appClass = jni->FindClass(ATTACH021_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL); + jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL); } #ifdef STATIC_BUILD @@ -138,9 +131,7 @@ if (!NSK_VERIFY(jvmti != NULL)) return JNI_ERR; - if (!NSK_VERIFY(registerNativeMethods(jni))) { - return JNI_ERR; - } + registerNativeMethods(jni); memset(&caps, 0, sizeof(caps)); caps.can_tag_objects = 1; diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/libattach021Agent00.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/libattach021Agent00.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/libattach021Agent00.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/libattach021Agent00.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Agent00.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Agent00.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Agent00.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Agent00.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include #include #include +#include "ExceptionCheckingJniEnv.hpp" extern "C" { @@ -64,7 +65,6 @@ JNIEXPORT jboolean JNICALL Java_nsk_jvmti_AttachOnDemand_attach022_attach022Target_shutdownAgent(JNIEnv * jni, jclass klass, jint expectedTaggedObjectsCounter) { - if (taggedObjectsCounter != expectedTaggedObjectsCounter) { success = 0; NSK_COMPLAIN2("ERROR: unexpected taggedObjectsCounter: %d (expected value is %d)\n", taggedObjectsCounter, expectedTaggedObjectsCounter); @@ -97,24 +97,16 @@ #define ATTACH022_TARGET_APP_CLASS_NAME "nsk/jvmti/AttachOnDemand/attach022/attach022Target" -int registerNativeMethods(JNIEnv* jni) { +void registerNativeMethods(JNIEnv* jni_env) { + ExceptionCheckingJniEnvPtr jni(jni_env); jclass appClass; JNINativeMethod nativeMethods[] = { { (char*)"shutdownAgent", (char*)"(I)Z", (void*) Java_nsk_jvmti_AttachOnDemand_attach022_attach022Target_shutdownAgent } }; jint nativeMethodsNumber = 1; - appClass = jni->FindClass(ATTACH022_TARGET_APP_CLASS_NAME); - if (!NSK_JNI_VERIFY(jni, appClass != NULL)) { - return NSK_FALSE; - } - - if (!NSK_JNI_VERIFY(jni, - (jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber) == 0))) { - return NSK_FALSE; - } - - return NSK_TRUE; + appClass = jni->FindClass(ATTACH022_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL); + jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL); } void JNICALL vmObjectAllocHandler(jvmtiEnv * jvmti, @@ -190,9 +182,7 @@ if (!NSK_VERIFY(jvmti != NULL)) return JNI_ERR; - if (!NSK_VERIFY(registerNativeMethods(jni))) { - return JNI_ERR; - } + registerNativeMethods(jni); if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("ObjectTagMonitor", &objectTagMonitor))) { return JNI_ERR; diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/libattach022Agent00.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/libattach022Agent00.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/libattach022Agent00.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/libattach022Agent00.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/ap04t003.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/ap04t003.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/ap04t003.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/ap04t003.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ #include #include #include "agent_common.h" - +#include "ExceptionCheckingJniEnv.hpp" #include "nsk_tools.h" #include "jni_tools.h" #include "JVMTITools.h" @@ -305,7 +305,7 @@ /***********************************************************************/ -static int startThread(JNIEnv* jni, jthread threadObj) { +static int startThread(jthread threadObj) { int success = NSK_TRUE; /* enter startLock */ @@ -334,46 +334,26 @@ } /** Create thread object for new agent thread. */ -static jthread newThreadObj(JNIEnv* jni) { +static jthread newThreadObj(JNIEnv* jni_env) { + ExceptionCheckingJniEnvPtr jni(jni_env); jclass thrClass; jmethodID cid; - jthread result = NULL; - - thrClass = jni->FindClass("java/lang/Thread"); - if (!NSK_JNI_VERIFY(jni, thrClass != NULL)) { - nsk_jvmti_setFailStatus(); - return result; - } - cid = jni->GetMethodID(thrClass, "", "()V"); - if (!NSK_JNI_VERIFY(jni, cid != NULL)) { - nsk_jvmti_setFailStatus(); - return result; - } - - result = jni->NewObject(thrClass, cid); - if (!NSK_JNI_VERIFY(jni, result != NULL)) { - nsk_jvmti_setFailStatus(); - return result; - } - - return result; + thrClass = jni->FindClass("java/lang/Thread", TRACE_JNI_CALL); + cid = jni->GetMethodID(thrClass, "", "()V", TRACE_JNI_CALL); + return jni->NewObject(thrClass, cid, TRACE_JNI_CALL); } /***********************************************************************/ /** Clean counters and start new agent thread with agent_start() body. */ -static int prepareToIteration (JNIEnv* jni) { +static int prepareToIteration(JNIEnv* jni) { jthread threadObj = NULL; setCounter(&iterationCount, 0); setCounter(&objectCount, 0); threadObj = newThreadObj(jni); - if (!NSK_VERIFY(threadObj != NULL)) { - nsk_jvmti_setFailStatus(); - return NSK_FALSE; - } /* enter endLock */ if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(endLock))) { @@ -381,11 +361,11 @@ } NSK_DISPLAY0("Starting new agent thread...\n"); - return startThread(jni, threadObj); + return startThread(threadObj); } /** Wait for new agent thread to complete. */ -static void afterIteration (JNIEnv* jni) { +static void afterIteration() { /* notify new agent thread (in case if not yet notified) */ notifyThread(); @@ -433,7 +413,7 @@ } NSK_DISPLAY0("IterateOverHeap finished.\n"); - afterIteration(jni); + afterIteration(); found = getCounter(&objectCount); NSK_DISPLAY1("Found tagged objects: %d\n", found); @@ -464,7 +444,7 @@ } NSK_DISPLAY0("IterateOverReachableObjects finished.\n"); - afterIteration(jni); + afterIteration(); found = getCounter(&objectCount); NSK_DISPLAY1("Found tagged objects: %d\n", found); @@ -495,7 +475,7 @@ } NSK_DISPLAY0("IterateOverInstancesOfClass finished.\n"); - afterIteration(jni); + afterIteration(); found = getCounter(&objectCount); NSK_DISPLAY1("Found tagged objects: %d\n", found); @@ -509,20 +489,16 @@ } JNIEXPORT void JNICALL -Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_runIterateOverObjectsReachableFromObject(JNIEnv* jni, +Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_runIterateOverObjectsReachableFromObject(JNIEnv* jni_env, jclass klass) { + ExceptionCheckingJniEnvPtr jni(jni_env); jobject root = NULL; int modified = 0; int found = 0; - root = jni->GetStaticObjectField(debugeeClass, rootFieldID); - if (!NSK_JNI_VERIFY(jni, root != NULL)) { - NSK_COMPLAIN0("GetStaticObjectField returned NULL for 'root' field value\n\n"); - nsk_jvmti_setFailStatus(); - return; - } + root = jni->GetStaticObjectField(debugeeClass, rootFieldID, TRACE_JNI_CALL); - if (!prepareToIteration(jni)) + if (!prepareToIteration(jni_env)) return; NSK_DISPLAY0("Calling IterateOverObjectsReachableFromObject...\n"); @@ -533,7 +509,7 @@ } NSK_DISPLAY0("IterateOverObjectsReachableFromObject finished.\n"); - afterIteration(jni); + afterIteration(); found = getCounter(&objectCount); NSK_DISPLAY1("Found tagged objects: %d\n", found); @@ -547,8 +523,8 @@ } static void JNICALL -agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { - +agentProc(jvmtiEnv* jvmti, JNIEnv* jni_env, void* arg) { + ExceptionCheckingJniEnvPtr jni(jni_env); NSK_DISPLAY0("Wait for debugee start\n\n"); if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) return; @@ -560,16 +536,11 @@ return; } - debugeeClass = (jclass) jni->NewGlobalRef(debugeeClass); - if (!NSK_JNI_VERIFY(jni, debugeeClass != NULL)) - return; + debugeeClass = (jclass) jni->NewGlobalRef(debugeeClass, TRACE_JNI_CALL); NSK_DISPLAY1("Find ID of 'root' field: %s\n", ROOT_SIGNATURE); - rootFieldID = jni->GetStaticFieldID(debugeeClass, "root", ROOT_SIGNATURE); - if (!NSK_JNI_VERIFY(jni, rootFieldID != NULL)) { - nsk_jvmti_setFailStatus(); - return; - } + rootFieldID = jni->GetStaticFieldID(debugeeClass, "root", + ROOT_SIGNATURE, TRACE_JNI_CALL); NSK_DISPLAY0("Let debugee to run test cases\n"); if (!NSK_VERIFY(nsk_jvmti_resumeSync())) @@ -579,7 +550,7 @@ if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) return; - NSK_TRACE(jni->DeleteGlobalRef(debugeeClass)); + jni->DeleteGlobalRef(debugeeClass, TRACE_JNI_CALL); NSK_TRACE(jvmti->DestroyRawMonitor(counterMonitor_ptr)); NSK_TRACE(jvmti->DestroyRawMonitor(startLock)); NSK_TRACE(jvmti->DestroyRawMonitor(runLock)); diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/libap04t003.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/libap04t003.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/libap04t003.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/libap04t003.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/bi01t001.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/bi01t001.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/bi01t001.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/bi01t001.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include #include "jvmti.h" #include "agent_common.h" +#include "ExceptionCheckingJniEnv.hpp" #include "jni_tools.h" #include "jvmti_tools.h" @@ -47,23 +48,20 @@ */ JNIEXPORT jboolean JNICALL Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t001_setNewByteCode(JNIEnv *jni_env, - jobject o, jbyteArray byteCode) { - + jobject o, + jbyteArray byteCode) { + ExceptionCheckingJniEnvPtr jni(jni_env); jbyte* elements; jboolean isCopy; - newClassSize = jni_env->GetArrayLength(byteCode); - if (!NSK_JNI_VERIFY(jni_env, newClassSize > 0)) { + newClassSize = jni->GetArrayLength(byteCode, TRACE_JNI_CALL); + if (newClassSize <= 0) { nsk_jvmti_setFailStatus(); return NSK_FALSE; } NSK_DISPLAY1("\t... got array size: %d\n", newClassSize); - elements = jni_env->GetByteArrayElements(byteCode, &isCopy); - if (!NSK_JNI_VERIFY(jni_env, elements != NULL)) { - nsk_jvmti_setFailStatus(); - return NSK_FALSE; - } + elements = jni->GetByteArrayElements(byteCode, &isCopy, TRACE_JNI_CALL); NSK_DISPLAY1("\t... got elements list: 0x%p\n", (void*)elements); if (!NSK_JVMTI_VERIFY(jvmti->Allocate(newClassSize, &newClassBytes))) { @@ -80,7 +78,7 @@ NSK_DISPLAY1("\t... copied bytecode: %d bytes\n", (int)newClassSize); NSK_DISPLAY1("\t... release elements list: 0x%p\n", (void*)elements); - NSK_TRACE(jni_env->ReleaseByteArrayElements(byteCode, elements, JNI_ABORT)); + jni->ReleaseByteArrayElements(byteCode, elements, JNI_ABORT, TRACE_JNI_CALL); NSK_DISPLAY0("\t... released\n"); return NSK_TRUE; } @@ -94,11 +92,8 @@ JNIEXPORT void JNICALL Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t001_setClass(JNIEnv *jni_env, jobject o, jclass cls) { - - oldClassDef.klass = (jclass) jni_env->NewGlobalRef(cls); - if (!NSK_JNI_VERIFY(jni_env, oldClassDef.klass != NULL)) { - nsk_jvmti_setFailStatus(); - } + ExceptionCheckingJniEnvPtr jni(jni_env); + oldClassDef.klass = (jclass) jni->NewGlobalRef(cls, TRACE_JNI_CALL); } /* ============================================================================= */ @@ -154,6 +149,7 @@ /** Agent algorithm. */ static void JNICALL agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { + ExceptionCheckingJniEnvPtr jni(agentJNI); /*Wait for debuggee to read new byte codes nsk_jvmti_waitForSync#1*/ NSK_DISPLAY0("Wait for debuggee to read new byte codes nsk_jvmti_waitForSync#1\n"); @@ -214,7 +210,7 @@ if (!nsk_jvmti_waitForSync(timeout)) return; - agentJNI->DeleteGlobalRef(oldClassDef.klass); + jni->DeleteGlobalRef(oldClassDef.klass, TRACE_JNI_CALL); NSK_DISPLAY0("Let debuggee to finish\n"); if (!nsk_jvmti_resumeSync()) diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/libbi01t001.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/libbi01t001.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/libbi01t001.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/libbi01t001.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ */ JNIEXPORT jboolean JNICALL Java_nsk_share_gc_lock_jni_BooleanArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jsize size, i; jbooleanArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jbooleanArray) env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + arr = (jbooleanArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = env->GetArrayLength(arr); + size = jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jboolean*) env->GetPrimitiveArrayCritical(arr, NULL); + pa = (jboolean*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = JNI_FALSE; } mssleep((long) sleepTime); - env->ReleasePrimitiveArrayCritical(arr, pa, 0); + jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, arr); + jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ */ JNIEXPORT jbyte JNICALL Java_nsk_share_gc_lock_jni_ByteArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jsize size, i; jbyteArray arr; @@ -45,18 +45,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jbyteArray) env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + arr = (jbyteArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = env->GetArrayLength(arr); + size = jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jbyte*) env->GetPrimitiveArrayCritical(arr, NULL); + pa = (jbyte*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -64,11 +64,11 @@ hash = 0; } mssleep((long) sleepTime); - env->ReleasePrimitiveArrayCritical(arr, pa, 0); + jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, arr); + jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ */ JNIEXPORT jchar JNICALL Java_nsk_share_gc_lock_jni_CharArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jsize size, i; jcharArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jcharArray) env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + arr = (jcharArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = env->GetArrayLength(arr); + size = jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); current_time = 0; enterTime /= 1000; while (current_time - start_time < enterTime) { - pa = (jchar*) env->GetPrimitiveArrayCritical(arr, NULL); + pa = (jchar*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - env->ReleasePrimitiveArrayCritical(arr, pa, 0); + jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, arr); + jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ */ JNIEXPORT jdouble JNICALL Java_nsk_share_gc_lock_jni_DoubleArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jsize size, i; jdoubleArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jdoubleArray) env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + arr = (jdoubleArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = env->GetArrayLength(arr); + size = jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jdouble*) env->GetPrimitiveArrayCritical(arr, NULL); + pa = (jdouble*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash += pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - env->ReleasePrimitiveArrayCritical(arr, pa, 0); + jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, arr); + jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ */ JNIEXPORT jfloat JNICALL Java_nsk_share_gc_lock_jni_FloatArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jsize size, i; jfloatArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jfloatArray) env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + arr = (jfloatArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = env->GetArrayLength(arr); + size = jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jfloat*) env->GetPrimitiveArrayCritical(arr, NULL); + pa = (jfloat*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash += pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - env->ReleasePrimitiveArrayCritical(arr, pa, 0); + jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, arr); + jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ */ JNIEXPORT jint JNICALL Java_nsk_share_gc_lock_jni_IntArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jsize size, i; jintArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jintArray) env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + arr = (jintArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = env->GetArrayLength(arr); + size = jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jint*) env->GetPrimitiveArrayCritical(arr, NULL); + pa = (jint*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - env->ReleasePrimitiveArrayCritical(arr, pa, 0); + jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, arr); + jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ */ JNIEXPORT jlong JNICALL Java_nsk_share_gc_lock_jni_LongArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jsize size, i; jlongArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jlongArray) env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + arr = (jlongArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = env->GetArrayLength(arr); + size = jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jlong*) env->GetPrimitiveArrayCritical(arr, NULL); + pa = (jlong*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - env->ReleasePrimitiveArrayCritical(arr, pa, 0); + jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, arr); + jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ */ JNIEXPORT jshort JNICALL Java_nsk_share_gc_lock_jni_ShortArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jsize size, i; jshortArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jshortArray) env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + arr = (jshortArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = env->GetArrayLength(arr); + size = jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jshort*) env->GetPrimitiveArrayCritical(arr, NULL); + pa = (jshort*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - env->ReleasePrimitiveArrayCritical(arr, pa, 0); + jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, arr); + jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ */ JNIEXPORT jchar JNICALL Java_nsk_share_gc_lock_jni_StringCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jsize size, i; jstring str; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - str = (jstring) env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + str = (jstring) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = env->GetStringLength(str); + size = jni->GetStringLength(str, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = env->GetStringCritical(str, NULL); + pa = jni->GetStringCritical(str, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = JNI_FALSE; } mssleep((long) sleepTime); - env->ReleaseStringCritical(str, pa); + jni->ReleaseStringCritical(str, pa, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, str); + jni->SetObjectField(o, objFieldId, str, TRACE_JNI_CALL); return hash; } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,29 +38,29 @@ */ JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIGlobalRefLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jobject obj; jobject gref; time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - obj = env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - gref = env->NewGlobalRef(obj); + gref = jni->NewGlobalRef(obj, TRACE_JNI_CALL); mssleep((long) sleepTime); - env->DeleteGlobalRef(gref); + jni->DeleteGlobalRef(gref, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, obj); + jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); } } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,29 +37,29 @@ */ JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNILocalRefLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jobject obj; jobject gref; time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - obj = env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - gref = env->NewLocalRef(obj); + gref = jni->NewLocalRef(obj, TRACE_JNI_CALL); mssleep((long) sleepTime); - env->DeleteLocalRef(gref); + jni->DeleteLocalRef(gref, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, obj); + jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); } } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,35 +37,35 @@ */ JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIRefLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jobject obj; jobject gref, lref, gwref; time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - obj = env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - gref = env->NewGlobalRef(obj); - lref = env->NewLocalRef(obj); - gwref = env->NewWeakGlobalRef(obj); + gref = jni->NewGlobalRef(obj, TRACE_JNI_CALL); + lref = jni->NewLocalRef(obj, TRACE_JNI_CALL); + gwref = jni->NewWeakGlobalRef(obj, TRACE_JNI_CALL); mssleep((long) sleepTime); - env->DeleteGlobalRef(gref); - env->DeleteLocalRef(lref); - env->DeleteWeakGlobalRef(gwref); + jni->DeleteGlobalRef(gref, TRACE_JNI_CALL); + jni->DeleteLocalRef(lref, TRACE_JNI_CALL); + jni->DeleteWeakGlobalRef(gwref, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, obj); + jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); } } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,30 +37,30 @@ */ JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIWeakGlobalRefLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr env(jni_env); + ExceptionCheckingJniEnvPtr jni(jni_env); jobject obj; jobject gref; time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = env->GetObjectClass(o); - objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;"); + jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - obj = env->GetObjectField(o, objFieldId); - env->SetObjectField(o, objFieldId, NULL); + obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - gref = env->NewWeakGlobalRef(obj); + gref = jni->NewWeakGlobalRef(obj, TRACE_JNI_CALL); mssleep((long) sleepTime); - env->DeleteWeakGlobalRef(gref); + jni->DeleteWeakGlobalRef(gref, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - env->SetObjectField(o, objFieldId, obj); + jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); } } diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, Google and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Google 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 @@ -26,62 +26,164 @@ #include #include "ExceptionCheckingJniEnv.hpp" +#include "nsk_tools.h" namespace { +static const char* get_dirname(const char* fullname) { + const char* p; + const char* base = fullname;; + + if (fullname == NULL) { + return NULL; + } + + for (p = fullname; *p != '\0'; p++) { + if (*p == '/' || *p == '\\') { + base = p + 1; + } + } + return base; +} + template class JNIVerifier { public: - JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_msg) - : _env(env), _base_msg(base_msg), _return_error(NULL) { + JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message, + int line, const char* file) + : _env(env), _base_message(base_message), _error_message(NULL), + _line(line), _file(get_dirname(file)) { + } + + // Until C++11 is supported, we have to write multiple template constructors. + template + JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message, + U parameter, + int line, const char* file) + : _env(env), _base_message(base_message), _error_message(NULL), + _line(line), _file(get_dirname(file)) { + PrintPreCall(parameter); + } + + template + JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message, + U parameter1, + V parameter2, + int line, const char* file) + : _env(env), _base_message(base_message), _error_message(NULL), + _line(line), _file(get_dirname(file)) { + PrintPreCall(parameter1, parameter2); + } + + template + JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message, + U parameter1, V parameter2, W parameter3, + int line, const char* file) + : _env(env), _base_message(base_message), _error_message(NULL), + _line(line), _file(get_dirname(file)) { + PrintPreCall(parameter1, parameter2, parameter3); } ~JNIVerifier() { + PrintPostCall(); + JNIEnv* jni_env = _env->GetJNIEnv(); - if (jni_env->ExceptionCheck()) { - _env->HandleError(_base_msg); + if (jni_env->ExceptionCheck() && !_error_message) { + _error_message = "internal error"; + } + + if (_error_message != NULL) { + GenerateErrorMessage(); + } + } + + int DecimalToAsciiRec(char *str, long line) { + if (line == 0) { + return 0; + } + + int remainder = line % 10; + long quotient = line / 10; + + int pos = DecimalToAsciiRec(str, quotient); + str[pos] = '0' + remainder; + return pos + 1; + } + + // Implementing a simple version of sprintf for "%d"... + void DecimalToAscii(char *str, int line) { + // Go to long so that the INT_MIN case can be handled seemlessly. + long internal_line = line; + if (internal_line == 0) { + str[0] = '0'; + str[1] = '\0'; return; } - if (_return_error != NULL) { - ProcessReturnError(); + if (internal_line < 0) { + *str = '-'; + internal_line *= -1; + str++; } + + str[DecimalToAsciiRec(str, internal_line)] = '\0'; } - void ProcessReturnError() { + void GenerateErrorMessage() { // This is error prone, but: // - Seems like we cannot use std::string (due to windows/solaris not // building when used, seemingly due to exception libraries not linking). // - Seems like we cannot use sprintf due to VS2013 (JDK-8213622). // // We are aiming to do: - // snprintf(full_message, len, "%s : %s", _base_msg, _return_error); + // snprintf(full_message, len, "JNI method %s : %s from %s : %d", _base_message, _error_message, + // _file, _line); // but will use strlen + memcpy instead. - size_t base_len = strlen(_base_msg); + const char* pre_message = "JNI method "; const char* between_msg = " : "; - size_t between_len = strlen(between_msg); - size_t return_len = strlen(_return_error); + const char* from_msg = " from "; - // +1 for the '\0' - size_t len = base_len + between_len + return_len + 1; + const char* file_name = _file ? _file : "Unknown File"; + const char* strs[] = { + pre_message, + _base_message, + between_msg, + _error_message, + from_msg, + file_name, + between_msg, + }; + + size_t msg_number = sizeof(strs) / sizeof(strs[0]); + size_t len = 0; + for (size_t i = 0; i < msg_number; i++) { + len += strlen(strs[i]); + } + + // 32-bit signed means 11 characters due to the '-'. + const int MAX_INTEGER_DIGITS = 11; + // Add for the line number and 1 for the '\0'. + len += MAX_INTEGER_DIGITS + 1; char* full_message = (char*) malloc(len); if (full_message == NULL) { - _env->HandleError(_return_error); + _env->HandleError(_error_message); return; } - // Now we construct the string using memcpy to not use sprintf/std::string + // Now we construct the string using strcat to not use sprintf/std::string // instead of: - // snprintf(full_message, len, "%s : %s", _base_msg, _return_error); - memcpy(full_message, _base_msg, base_len); - memcpy(full_message + base_len, between_msg, between_len); - memcpy(full_message + base_len + between_len, _return_error, return_len); - full_message[len - 1] = '\0'; - - // -1 due to the '\0' not counted by strlen but is counted for the allocation. - if (strlen(full_message) != len - 1) { - _env->GetJNIEnv()->FatalError("Length of message is not what was expected"); + // snprintf(full_message, len, "JNI method %s : %s from %s:%d", _base_message, + // _error_message, _file, _line); + full_message[0] = '\0'; + for (size_t i = 0; i < msg_number; i++) { + strcat(full_message, strs[i]); + } + + DecimalToAscii(full_message, _line); + + if (strlen(full_message) >= len) { + _env->GetJNIEnv()->FatalError("Final length of message is not what was expected"); } _env->HandleError(full_message); @@ -90,95 +192,240 @@ T ResultNotNull(T ptr) { if (ptr == NULL) { - _return_error = "Return is NULL"; + _error_message = "Return is NULL"; } return ptr; } + T ResultIsZero(T value) { + if (value != 0) { + _error_message = "Return is not zero"; + } + return value; + } + + void PrintPreCallHeader() { + if (!nsk_getVerboseMode()) { + return; + } + + fprintf(stdout, ">> Calling JNI method %s from %s:%d\n", + _base_message, _file, _line); + fprintf(stdout, ">> Calling with these parameter(s):\n"); + } + + // Until we can actually link with C++ more uniformely across architectures, + // we have to do this... + template + void PrintParameter(U* ptr) { + fprintf(stdout, "\t%p\n", ptr); + } + + void PrintParameter(int value) { + fprintf(stdout, "\t%d\n", value); + } + + // Until C++11 is supported, we have to write multiple PrintPreCall. + template + void PrintPreCall(U first_parameter) { + if (!nsk_getVerboseMode()) { + return; + } + + PrintPreCallHeader(); + PrintParameter(first_parameter); + } + + template + void PrintPreCall(U parameter1, V parameter2) { + if (!nsk_getVerboseMode()) { + return; + } + + PrintPreCallHeader(); + PrintParameter(parameter1); + PrintParameter(parameter2); + } + + template + void PrintPreCall(U parameter1, V parameter2, W parameter3) { + if (!nsk_getVerboseMode()) { + return; + } + + PrintPreCallHeader(); + PrintParameter(parameter1); + PrintParameter(parameter2); + PrintParameter(parameter3); + } + + void PrintPostCall() { + if (!nsk_getVerboseMode()) { + return; + } + + fprintf(stderr, "<< Called JNI method %s from %s:%d\n", + _base_message, _file, _line); + } + private: ExceptionCheckingJniEnv* _env; - const char* const _base_msg; - const char* _return_error; + const char* const _base_message; + const char* _error_message; + int _line; + const char* const _file; }; } -jclass ExceptionCheckingJniEnv::GetObjectClass(jobject obj) { - JNIVerifier marker(this, "GetObjectClass"); +jclass ExceptionCheckingJniEnv::FindClass(const char *class_name, + int line, const char* file_name) { + JNIVerifier marker(this, "FindClass", class_name, line, file_name); + return marker.ResultNotNull(_jni_env->FindClass(class_name)); +} + +jint ExceptionCheckingJniEnv::RegisterNatives(jclass clazz, + const JNINativeMethod *methods, + jint nMethods, + int line, + const char* file_name) { + JNIVerifier marker(this, "RegisterNatives", methods, nMethods, line, file_name); + return marker.ResultIsZero(_jni_env->RegisterNatives(clazz, methods, nMethods)); +} + +jclass ExceptionCheckingJniEnv::GetObjectClass(jobject obj, int line, + const char* file_name) { + JNIVerifier marker(this, "GetObjectClass", obj, line, file_name); return marker.ResultNotNull(_jni_env->GetObjectClass(obj)); } -jfieldID ExceptionCheckingJniEnv::GetFieldID(jclass klass, const char *name, const char* type) { - JNIVerifier marker(this, "GetFieldID"); +jfieldID ExceptionCheckingJniEnv::GetStaticFieldID(jclass klass, const char *name, + const char* type, + int line, const char* file_name) { + JNIVerifier marker(this, "GetStaticFieldID", klass, name, type, + line, file_name); + return marker.ResultNotNull(_jni_env->GetStaticFieldID(klass, name, type)); +} + +jfieldID ExceptionCheckingJniEnv::GetFieldID(jclass klass, const char *name, + const char* type, + int line, const char* file_name) { + JNIVerifier marker(this, "GetFieldID", klass, name, type, line, file_name); return marker.ResultNotNull(_jni_env->GetFieldID(klass, name, type)); } -jobject ExceptionCheckingJniEnv::GetObjectField(jobject obj, jfieldID field) { - JNIVerifier marker(this, "GetObjectField"); +jobject ExceptionCheckingJniEnv::GetStaticObjectField(jclass klass, jfieldID field, + int line, const char* file_name) { + JNIVerifier marker(this, "GetStaticObjectField", klass, field, + line, file_name); + return marker.ResultNotNull(_jni_env->GetStaticObjectField(klass, field)); +} + +jobject ExceptionCheckingJniEnv::GetObjectField(jobject obj, jfieldID field, + int line, const char* file_name) { + JNIVerifier marker(this, "GetObjectField", obj, field, line, file_name); return marker.ResultNotNull(_jni_env->GetObjectField(obj, field)); } -void ExceptionCheckingJniEnv::SetObjectField(jobject obj, jfieldID field, jobject value) { - JNIVerifier<> marker(this, "SetObjectField"); +void ExceptionCheckingJniEnv::SetObjectField(jobject obj, jfieldID field, jobject value, + int line, const char* file_name) { + JNIVerifier<> marker(this, "SetObjectField", obj, field, value, line, file_name); _jni_env->SetObjectField(obj, field, value); } -jobject ExceptionCheckingJniEnv::NewGlobalRef(jobject obj) { - JNIVerifier marker(this, "NewGlobalRef"); +jobject ExceptionCheckingJniEnv::NewGlobalRef(jobject obj, int line, const char* file_name) { + JNIVerifier marker(this, "NewGlobalRef", obj, line, file_name); return marker.ResultNotNull(_jni_env->NewGlobalRef(obj)); } -void ExceptionCheckingJniEnv::DeleteGlobalRef(jobject obj) { - JNIVerifier<> marker(this, "DeleteGlobalRef"); +void ExceptionCheckingJniEnv::DeleteGlobalRef(jobject obj, int line, const char* file_name) { + JNIVerifier<> marker(this, "DeleteGlobalRef", obj, line, file_name); _jni_env->DeleteGlobalRef(obj); } -jobject ExceptionCheckingJniEnv::NewLocalRef(jobject obj) { - JNIVerifier marker(this, "NewLocalRef"); +jobject ExceptionCheckingJniEnv::NewLocalRef(jobject obj, int line, const char* file_name) { + JNIVerifier marker(this, "NewLocalRef", obj, line, file_name); return marker.ResultNotNull(_jni_env->NewLocalRef(obj)); } -void ExceptionCheckingJniEnv::DeleteLocalRef(jobject obj) { - JNIVerifier<> marker(this, "DeleteLocalRef"); +void ExceptionCheckingJniEnv::DeleteLocalRef(jobject obj, int line, const char* file_name) { + JNIVerifier<> marker(this, "DeleteLocalRef", obj, line, file_name); _jni_env->DeleteLocalRef(obj); } -jweak ExceptionCheckingJniEnv::NewWeakGlobalRef(jobject obj) { - JNIVerifier marker(this, "NewWeakGlobalRef"); +jweak ExceptionCheckingJniEnv::NewWeakGlobalRef(jobject obj, int line, const char* file_name) { + JNIVerifier marker(this, "NewWeakGlobalRef", obj, line, file_name); return marker.ResultNotNull(_jni_env->NewWeakGlobalRef(obj)); } -void ExceptionCheckingJniEnv::DeleteWeakGlobalRef(jweak weak_ref) { - JNIVerifier<> marker(this, "DeleteWeakGlobalRef"); +void ExceptionCheckingJniEnv::DeleteWeakGlobalRef(jweak weak_ref, int line, const char* file_name) { + JNIVerifier<> marker(this, "DeleteWeakGlobalRef", weak_ref, line, file_name); _jni_env->DeleteWeakGlobalRef(weak_ref); } -jsize ExceptionCheckingJniEnv::GetArrayLength(jarray array) { - JNIVerifier<> marker(this, "GetArrayLength"); +jsize ExceptionCheckingJniEnv::GetArrayLength(jarray array, int line, const char* file_name) { + JNIVerifier<> marker(this, "GetArrayLength", array, line, file_name); return _jni_env->GetArrayLength(array); } -jsize ExceptionCheckingJniEnv::GetStringLength(jstring str) { - JNIVerifier<> marker(this, "GetStringLength"); +jsize ExceptionCheckingJniEnv::GetStringLength(jstring str, int line, const char* file_name) { + JNIVerifier<> marker(this, "GetStringLength", str, line, file_name); return _jni_env->GetStringLength(str); } -void* ExceptionCheckingJniEnv::GetPrimitiveArrayCritical(jarray array, jboolean* isCopy) { - JNIVerifier<> marker(this, "GetPrimitiveArrayCritical"); - return marker.ResultNotNull(_jni_env->GetPrimitiveArrayCritical(array, isCopy)); +void* ExceptionCheckingJniEnv::GetPrimitiveArrayCritical(jarray array, jboolean* is_copy, + int line, const char* file_name) { + JNIVerifier<> marker(this, "GetPrimitiveArrayCritical", array, is_copy, line, file_name); + return marker.ResultNotNull(_jni_env->GetPrimitiveArrayCritical(array, is_copy)); } -void ExceptionCheckingJniEnv::ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode) { - JNIVerifier<> marker(this, "ReleasePrimitiveArrayCritical"); +void ExceptionCheckingJniEnv::ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode, + int line, const char* file_name) { + JNIVerifier<> marker(this, "ReleasePrimitiveArrayCritical", array, carray, mode, + line, file_name); _jni_env->ReleasePrimitiveArrayCritical(array, carray, mode); } -const jchar* ExceptionCheckingJniEnv::GetStringCritical(jstring str, jboolean* isCopy) { - JNIVerifier marker(this, "GetPrimitiveArrayCritical"); - return marker.ResultNotNull(_jni_env->GetStringCritical(str, isCopy)); +const jchar* ExceptionCheckingJniEnv::GetStringCritical(jstring str, jboolean* is_copy, + int line, const char* file_name) { + JNIVerifier marker(this, "GetPrimitiveArrayCritical", str, is_copy, + line, file_name); + return marker.ResultNotNull(_jni_env->GetStringCritical(str, is_copy)); } -void ExceptionCheckingJniEnv::ReleaseStringCritical(jstring str, const jchar* carray) { - JNIVerifier<> marker(this, "ReleaseStringCritical"); +void ExceptionCheckingJniEnv::ReleaseStringCritical(jstring str, const jchar* carray, + int line, const char* file_name) { + JNIVerifier<> marker(this, "ReleaseStringCritical", str, carray, line, file_name); _jni_env->ReleaseStringCritical(str, carray); } + +jbyte* ExceptionCheckingJniEnv::GetByteArrayElements(jbyteArray array, jboolean* is_copy, + int line, const char* file_name) { + JNIVerifier marker(this, "GetByteArrayElements", array, is_copy, line, file_name); + return marker.ResultNotNull(_jni_env->GetByteArrayElements(array, is_copy)); +} + +void ExceptionCheckingJniEnv::ReleaseByteArrayElements(jbyteArray array, jbyte* byte_array, jint mode, + int line, const char* file_name) { + JNIVerifier<> marker(this, "ReleaseByteArrayElements", array, byte_array, mode, + line, file_name); + _jni_env->ReleaseByteArrayElements(array, byte_array, mode); +} + +jmethodID ExceptionCheckingJniEnv::GetMethodID(jclass klass, const char* name, const char* sig, + int line, const char* file_name) { + JNIVerifier marker(this, "GetMethodID", klass, name, sig, line, file_name); + return marker.ResultNotNull(_jni_env->GetMethodID(klass, name, sig)); +} + +jobject ExceptionCheckingJniEnv::NewObject(jclass klass, jmethodID methodID, + int line, const char* file_name, ...) { + // In the case of NewObject, we miss the extra arguments passed to NewObject sadly. + JNIVerifier marker(this, "NewObject", klass, methodID, line, file_name); + + va_list args; + va_start(args, file_name); + jobject result = marker.ResultNotNull(_jni_env->NewObjectV(klass, methodID, args)); + va_end(args); + return result; +} diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.hpp openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.hpp --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.hpp 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.hpp 2019-04-24 19:25:41.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, Google and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Google 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 @@ -46,40 +46,65 @@ * * Can be simplified to: * ... ExceptionCheckingJniEnv* env ... - * jclass klass = env->GetObjectClass(o); + * jclass klass = env->GetObjectClass(o, TRACE_JNI_CALL); * * Where now the JNI Exception checking and the NULL return checking are done * internally and will perform whatever action the ErrorHandler requires. * + * Note the TRACE_JNI_CALL parameter that allows to trace where the call is + * happening from for debugging. + * * By default, the error handler describes the exception via the JNI * ExceptionDescribe method and calls FatalError. - * - * Note: at a future date, this will also include the tracing mechanism done in - * NSK_VERIFY, which will thus embed its logic into the ExceptionCheckingJniEnv - * and clearing that up for the code readers and writers. */ + +#define TRACE_JNI_CALL __LINE__, __FILE__ + class ExceptionCheckingJniEnv { public: // JNIEnv API redefinitions. - jfieldID GetFieldID(jclass klass, const char *name, const char* type); - jclass GetObjectClass(jobject obj); - jobject GetObjectField(jobject obj, jfieldID field); - void SetObjectField(jobject obj, jfieldID field, jobject value); - - jsize GetArrayLength(jarray array); - jsize GetStringLength(jstring str); - - void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy); - void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode); - const jchar* GetStringCritical(jstring str, jboolean* isCopy); - void ReleaseStringCritical(jstring str, const jchar* carray); - - jobject NewGlobalRef(jobject obj); - void DeleteGlobalRef(jobject obj); - jobject NewLocalRef(jobject ref); - void DeleteLocalRef(jobject ref); - jweak NewWeakGlobalRef(jobject obj); - void DeleteWeakGlobalRef(jweak obj); + jclass FindClass(const char *name, int line, const char* file_name); + + jfieldID GetStaticFieldID(jclass klass, const char* name, const char* type, + int line, const char* file_name); + jfieldID GetFieldID(jclass klass, const char* name, const char* type, + int line, const char* file_name); + jmethodID GetMethodID(jclass klass, const char* name, const char* sig, + int line, const char* file_name); + + jclass GetObjectClass(jobject obj, int line, const char* file_name); + jobject GetObjectField(jobject obj, jfieldID field, int line, const char* file_name); + jobject GetStaticObjectField(jclass kls, jfieldID field, int line, const char* file_name); + void SetObjectField(jobject obj, jfieldID field, jobject value, + int line, const char* file_name); + + jsize GetArrayLength(jarray array, int line, const char* file_name); + jsize GetStringLength(jstring str, int line, const char* file_name); + + void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy, + int line, const char* file_name); + void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode, + int line, const char* file_name); + const jchar* GetStringCritical(jstring str, jboolean* isCopy, + int line, const char* file_name); + void ReleaseStringCritical(jstring str, const jchar* carray, + int line, const char* file_name); + + jbyte* GetByteArrayElements(jbyteArray array, jboolean* isCopy, + int line, const char* file_name); + void ReleaseByteArrayElements(jbyteArray array, jbyte* byte_array, jint mode, + int line, const char* file_name); + jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods, + int line, const char* file_name); + + jobject NewObject(jclass kls, jmethodID methodID, + int line, const char* file_name, ...); + jobject NewGlobalRef(jobject obj, int line, const char* file_name); + void DeleteGlobalRef(jobject obj, int line, const char* file_name); + jobject NewLocalRef(jobject ref, int line, const char* file_name); + void DeleteLocalRef(jobject ref, int line, const char* file_name); + jweak NewWeakGlobalRef(jobject obj, int line, const char* file_name); + void DeleteWeakGlobalRef(jweak obj, int line, const char* file_name); // ExceptionCheckingJniEnv methods. JNIEnv* GetJNIEnv() { diff -Nru openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/Test.java openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/Test.java --- openjdk-13-13~17/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/Test.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/Test.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ * @run driver vm.mlvm.share.IndifiedClassesBuilder * * @run main/othervm - * -XX:+BytecodeVerificationLocal + * -Xverify:all * vm.mlvm.anonloader.stress.parallelLoad.Test * -threadsPerCpu 4 * -threadsExtra 20 diff -Nru openjdk-13-13~17/test/jdk/com/sun/jdi/lib/jdb/Debuggee.java openjdk-13-13~18/test/jdk/com/sun/jdi/lib/jdb/Debuggee.java --- openjdk-13-13~17/test/jdk/com/sun/jdi/lib/jdb/Debuggee.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/com/sun/jdi/lib/jdb/Debuggee.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,6 +65,7 @@ public static class Launcher { private final String mainClass; private final List options = new LinkedList<>(); + private String vmOptions = null; private String transport = "dt_socket"; private String address = null; private boolean suspended = true; @@ -81,6 +82,10 @@ this.options.addAll(options); return this; } + public Launcher addVMOptions(String vmOptions) { + this.vmOptions = vmOptions; + return this; + } // default is "dt_socket" public Launcher setTransport(String value) { transport = value; @@ -104,6 +109,9 @@ public ProcessBuilder prepare() { List debuggeeArgs = new LinkedList<>(); + if (vmOptions != null) { + debuggeeArgs.add(vmOptions); + } debuggeeArgs.add("-agentlib:jdwp=transport=" + transport + (address == null ? "" : ",address=" + address) + ",server=y,suspend=" + (suspended ? "y" : "n")); diff -Nru openjdk-13-13~17/test/jdk/com/sun/jdi/lib/jdb/JdbTest.java openjdk-13-13~18/test/jdk/com/sun/jdi/lib/jdb/JdbTest.java --- openjdk-13-13~17/test/jdk/com/sun/jdi/lib/jdb/JdbTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/com/sun/jdi/lib/jdb/JdbTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ public final String debuggeeClass; public final List debuggeeOptions = new LinkedList<>(); public String sourceFilename; + public String vmOptions = null; public LaunchOptions(String debuggeeClass) { this.debuggeeClass = debuggeeClass; @@ -56,6 +57,10 @@ sourceFilename = name; return this; } + public LaunchOptions addVMOptions(String vmOptions) { + this.vmOptions = vmOptions; + return this; + } } public JdbTest(LaunchOptions launchOptions) { @@ -72,7 +77,7 @@ protected Jdb jdb; protected Debuggee debuggee; - private final LaunchOptions launchOptions; + protected LaunchOptions launchOptions; // returns the whole jdb output as a string public String getJdbOutput() { @@ -108,6 +113,7 @@ // launch debuggee debuggee = Debuggee.launcher(launchOptions.debuggeeClass) .addOptions(launchOptions.debuggeeOptions) + .addVMOptions(launchOptions.vmOptions) .launch(); // launch jdb diff -Nru openjdk-13-13~17/test/jdk/com/sun/jdi/RedefineAddPrivateMethod.java openjdk-13-13~18/test/jdk/com/sun/jdi/RedefineAddPrivateMethod.java --- openjdk-13-13~17/test/jdk/com/sun/jdi/RedefineAddPrivateMethod.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/com/sun/jdi/RedefineAddPrivateMethod.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,8 +46,12 @@ } public class RedefineAddPrivateMethod extends JdbTest { + static private final String ALLOW_ADD_DELETE_OPTION = "-XX:+AllowRedefinitionToAddDeleteMethods"; + public static void main(String argv[]) { - new RedefineAddPrivateMethod().run(); + RedefineAddPrivateMethod test = new RedefineAddPrivateMethod(); + test.launchOptions.addVMOptions(ALLOW_ADD_DELETE_OPTION); + test.run(); } private RedefineAddPrivateMethod() { diff -Nru openjdk-13-13~17/test/jdk/java/awt/font/TextLayout/FontLayoutStressTest.java openjdk-13-13~18/test/jdk/java/awt/font/TextLayout/FontLayoutStressTest.java --- openjdk-13-13~17/test/jdk/java/awt/font/TextLayout/FontLayoutStressTest.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/test/jdk/java/awt/font/TextLayout/FontLayoutStressTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2019 JetBrains s.r.o. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8220231 + * @summary Cache HarfBuzz face object for same font's text layout calls + * @comment Test layout operations for the same font performed simultaneously + * from multiple threads + */ + +import java.awt.Font; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicReference; + +public class FontLayoutStressTest { + private static final int NUMBER_OF_THREADS = + Runtime.getRuntime().availableProcessors() * 2; + private static final long TIME_TO_RUN_NS = 1_000_000_000; // 1 second + private static final Font FONT = new Font(Font.SERIF, Font.PLAIN, 12); + private static final FontRenderContext FRC = new FontRenderContext(null, + false, false); + private static final char[] TEXT = "Lorem ipsum dolor sit amet, ..." + .toCharArray(); + + private static double doLayout() { + GlyphVector gv = FONT.layoutGlyphVector(FRC, TEXT, 0, TEXT.length, + Font.LAYOUT_LEFT_TO_RIGHT); + return gv.getGlyphPosition(gv.getNumGlyphs()).getX(); + } + + public static void main(String[] args) throws Throwable { + double expectedWidth = doLayout(); + AtomicReference throwableRef = new AtomicReference<>(); + CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_THREADS); + List threads = new ArrayList<>(); + for (int i = 0; i < NUMBER_OF_THREADS; i++) { + Thread thread = new Thread(() -> { + try { + barrier.await(); + long timeToStop = System.nanoTime() + TIME_TO_RUN_NS; + while (System.nanoTime() < timeToStop) { + double width = doLayout(); + if (width != expectedWidth) { + throw new RuntimeException( + "Unexpected layout result"); + } + } + } catch (Throwable e) { + throwableRef.set(e); + } + }); + threads.add(thread); + thread.start(); + } + for (Thread thread : threads) { + thread.join(); + } + Throwable throwable = throwableRef.get(); + if (throwable != null) { + throw throwable; + } + } +} diff -Nru openjdk-13-13~17/test/jdk/java/lang/instrument/RedefineAddDeleteMethod/DeleteMethodHandle/MethodHandleDeletedMethod.java openjdk-13-13~18/test/jdk/java/lang/instrument/RedefineAddDeleteMethod/DeleteMethodHandle/MethodHandleDeletedMethod.java --- openjdk-13-13~17/test/jdk/java/lang/instrument/RedefineAddDeleteMethod/DeleteMethodHandle/MethodHandleDeletedMethod.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/java/lang/instrument/RedefineAddDeleteMethod/DeleteMethodHandle/MethodHandleDeletedMethod.java 2019-04-24 19:25:41.000000000 +0000 @@ -33,7 +33,7 @@ * @compile ../../NamedBuffer.java * @compile redef/Xost.java * @run main RedefineClassHelper - * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+update*=debug,membername+table=debug MethodHandleDeletedMethod + * @run main/othervm -XX:+AllowRedefinitionToAddDeleteMethods -javaagent:redefineagent.jar -Xlog:redefine+class+update*=debug,membername+table=debug MethodHandleDeletedMethod */ import java.io.File; diff -Nru openjdk-13-13~17/test/jdk/java/lang/instrument/RedefineMethodAddInvoke.sh openjdk-13-13~18/test/jdk/java/lang/instrument/RedefineMethodAddInvoke.sh --- openjdk-13-13~17/test/jdk/java/lang/instrument/RedefineMethodAddInvoke.sh 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/java/lang/instrument/RedefineMethodAddInvoke.sh 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,7 @@ mv RedefineMethodAddInvokeTarget.class RedefineMethodAddInvokeTarget_2.class "${JAVA}" ${TESTVMOPTS} -javaagent:RedefineMethodAddInvokeAgent.jar \ + -XX:+AllowRedefinitionToAddDeleteMethods \ -classpath "${TESTCLASSES}" RedefineMethodAddInvokeApp > output.log 2>&1 cat output.log diff -Nru openjdk-13-13~17/test/jdk/java/lang/instrument/RedefineMethodDelInvoke.sh openjdk-13-13~18/test/jdk/java/lang/instrument/RedefineMethodDelInvoke.sh --- openjdk-13-13~17/test/jdk/java/lang/instrument/RedefineMethodDelInvoke.sh 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/java/lang/instrument/RedefineMethodDelInvoke.sh 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,7 @@ mv RedefineMethodDelInvokeTarget.class RedefineMethodDelInvokeTarget_2.class "${JAVA}" ${TESTVMOPTS} -javaagent:RedefineMethodDelInvokeAgent.jar \ + -XX:+AllowRedefinitionToAddDeleteMethods \ -classpath "${TESTCLASSES}" RedefineMethodDelInvokeApp > output.log 2>&1 result=$? diff -Nru openjdk-13-13~17/test/jdk/java/lang/instrument/RedefineMethodInBacktrace.sh openjdk-13-13~18/test/jdk/java/lang/instrument/RedefineMethodInBacktrace.sh --- openjdk-13-13~17/test/jdk/java/lang/instrument/RedefineMethodInBacktrace.sh 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/java/lang/instrument/RedefineMethodInBacktrace.sh 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -69,6 +69,7 @@ "${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . RedefineMethodInBacktraceTargetB.java "${JAVA}" ${TESTVMOPTS} -javaagent:RedefineMethodInBacktraceAgent.jar \ + -XX:+AllowRedefinitionToAddDeleteMethods \ -classpath "${TESTCLASSES}" RedefineMethodInBacktraceApp > output.log 2>&1 RUN_RESULT=$? diff -Nru openjdk-13-13~17/test/jdk/java/net/httpclient/DigestEchoServer.java openjdk-13-13~18/test/jdk/java/net/httpclient/DigestEchoServer.java --- openjdk-13-13~17/test/jdk/java/net/httpclient/DigestEchoServer.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/java/net/httpclient/DigestEchoServer.java 2019-04-24 19:25:41.000000000 +0000 @@ -80,6 +80,8 @@ Boolean.parseBoolean(System.getProperty("test.debug", "false")); public static final boolean NO_LINGER = Boolean.parseBoolean(System.getProperty("test.nolinger", "false")); + public static final boolean TUNNEL_REQUIRES_HOST = + Boolean.parseBoolean(System.getProperty("test.requiresHost", "false")); public enum HttpAuthType { SERVER, PROXY, SERVER307, PROXY305 /* add PROXY_AND_SERVER and SERVER_PROXY_NONE */ @@ -1522,6 +1524,36 @@ } } + boolean badRequest(StringBuilder response, String hostport, List hosts) { + String message = null; + if (hosts.isEmpty()) { + message = "No host header provided\r\n"; + } else if (hosts.size() > 1) { + message = "Multiple host headers provided\r\n"; + for (String h : hosts) { + message = message + "host: " + h + "\r\n"; + } + } else { + String h = hosts.get(0); + if (!hostport.equalsIgnoreCase(h) + && !hostport.equalsIgnoreCase(h + ":80") + && !hostport.equalsIgnoreCase(h + ":443")) { + message = "Bad host provided: [" + h + + "] doesnot match [" + hostport + "]\r\n"; + } + } + if (message != null) { + int length = message.getBytes(StandardCharsets.UTF_8).length; + response.append("HTTP/1.1 400 BadRequest\r\n") + .append("Content-Length: " + length) + .append("\r\n\r\n") + .append(message); + return true; + } + + return false; + } + boolean authorize(StringBuilder response, String requestLine, String headers) { if (authorization != null) { return authorization.authorize(response, requestLine, headers); @@ -1635,6 +1667,7 @@ assert connect.equalsIgnoreCase("connect"); String hostport = tokenizer.nextToken(); InetSocketAddress targetAddress; + List hosts = new ArrayList<>(); try { URI uri = new URI("https", hostport, "/", null, null); int port = uri.getPort(); @@ -1659,9 +1692,30 @@ System.out.println(now() + "Tunnel: Reading header: " + (line = readLine(ccis))); headers.append(line).append("\r\n"); + int index = line.indexOf(':'); + if (index >= 0) { + String key = line.substring(0, index).trim(); + if (key.equalsIgnoreCase("host")) { + hosts.add(line.substring(index+1).trim()); + } + } } - StringBuilder response = new StringBuilder(); + if (TUNNEL_REQUIRES_HOST) { + if (badRequest(response, hostport, hosts)) { + System.out.println(now() + "Tunnel: Sending " + response); + // send the 400 response + pw.print(response.toString()); + pw.flush(); + toClose.close(); + continue; + } else { + assert hosts.size() == 1; + System.out.println(now() + + "Tunnel: Host header verified " + hosts); + } + } + final boolean authorize = authorize(response, requestLine, headers.toString()); if (!authorize) { System.out.println(now() + "Tunnel: Sending " diff -Nru openjdk-13-13~17/test/jdk/java/net/httpclient/HttpsTunnelTest.java openjdk-13-13~18/test/jdk/java/net/httpclient/HttpsTunnelTest.java --- openjdk-13-13~17/test/jdk/java/net/httpclient/HttpsTunnelTest.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/java/net/httpclient/HttpsTunnelTest.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,8 +47,9 @@ * proxy P is downgraded to HTTP/1.1, then a new h2 request * going to a different host through the same proxy will not * be preemptively downgraded. That, is the stack should attempt - * a new h2 connection to the new host. - * @bug 8196967 + * a new h2 connection to the new host. It also verifies that + * the stack sends the appropriate "host" header to the proxy. + * @bug 8196967 8222527 * @library /test/lib http2/server * @build jdk.test.lib.net.SimpleSSLContext HttpServerAdapters DigestEchoServer HttpsTunnelTest * @modules java.net.http/jdk.internal.net.http.common @@ -58,7 +59,14 @@ * java.base/sun.net.www.http * java.base/sun.net.www * java.base/sun.net - * @run main/othervm -Djdk.internal.httpclient.debug=true HttpsTunnelTest + * @run main/othervm -Dtest.requiresHost=true + * -Djdk.httpclient.HttpClient.log=headers + * -Djdk.internal.httpclient.debug=true HttpsTunnelTest + * @run main/othervm -Dtest.requiresHost=true + * -Djdk.httpclient.allowRestrictedHeaders=host + * -Djdk.httpclient.HttpClient.log=headers + * -Djdk.internal.httpclient.debug=true HttpsTunnelTest + * */ public class HttpsTunnelTest implements HttpServerAdapters { @@ -116,6 +124,18 @@ try { URI uri1 = new URI("https://" + http1Server.serverAuthority() + "/foo/https1"); URI uri2 = new URI("https://" + http2Server.serverAuthority() + "/foo/https2"); + + boolean provideCustomHost = "host".equalsIgnoreCase( + System.getProperty("jdk.httpclient.allowRestrictedHeaders","")); + + String customHttp1Host = null, customHttp2Host = null; + if (provideCustomHost) { + customHttp1Host = makeCustomHostString(http1Server, uri1); + out.println("HTTP/1.1: <" + uri1 + "> [custom host: " + customHttp1Host + "]"); + customHttp2Host = makeCustomHostString(http2Server, uri2); + out.println("HTTP/2: <" + uri2 + "> [custom host: " + customHttp2Host + "]"); + } + ProxySelector ps = ProxySelector.of(proxy.getProxyAddress()); //HttpClient.Builder.NO_PROXY; HttpsTunnelTest test = new HttpsTunnelTest(); @@ -126,11 +146,12 @@ assert lines.size() == data.length; String body = lines.stream().collect(Collectors.joining("\r\n")); HttpRequest.BodyPublisher reqBody = HttpRequest.BodyPublishers.ofString(body); - HttpRequest req1 = HttpRequest + HttpRequest.Builder req1Builder = HttpRequest .newBuilder(uri1) .version(Version.HTTP_2) - .POST(reqBody) - .build(); + .POST(reqBody); + if (provideCustomHost) req1Builder.header("host", customHttp1Host); + HttpRequest req1 = req1Builder.build(); out.println("\nPosting to HTTP/1.1 server at: " + req1); HttpResponse> response = client.send(req1, BodyHandlers.ofLines()); out.println("Checking response..."); @@ -145,12 +166,14 @@ if (!lines.equals(respLines)) { throw new RuntimeException("Unexpected response 1: " + respLines); } + HttpRequest.BodyPublisher reqBody2 = HttpRequest.BodyPublishers.ofString(body); - HttpRequest req2 = HttpRequest + HttpRequest.Builder req2Builder = HttpRequest .newBuilder(uri2) .version(Version.HTTP_2) - .POST(reqBody2) - .build(); + .POST(reqBody2); + if (provideCustomHost) req2Builder.header("host", customHttp2Host); + HttpRequest req2 = req2Builder.build(); out.println("\nPosting to HTTP/2 server at: " + req2); response = client.send(req2, BodyHandlers.ofLines()); out.println("Checking response..."); @@ -176,4 +199,26 @@ } } + /** + * Builds a custom host string that is different to what is in the URI + * authority, that is textually different than what the stack would + * send. For CONNECT we should ignore any custom host settings. + * The tunnelling proxy will fail with badRequest 400 if it receives + * the custom host instead of the expected URI authority string. + * @param server The target server. + * @param uri The URI to the target server + * @return a host value for the custom host header. + */ + static final String makeCustomHostString(HttpTestServer server, URI uri) { + String customHttpHost; + if (server.serverAuthority().contains("localhost")) { + customHttpHost = InetAddress.getLoopbackAddress().getHostAddress(); + } else { + customHttpHost = InetAddress.getLoopbackAddress().getHostName(); + } + if (customHttpHost.contains(":")) customHttpHost = "[" + customHttpHost + "]"; + if (uri.getPort() != -1) customHttpHost = customHttpHost + ":" + uri.getPort(); + return customHttpHost; + } + } diff -Nru openjdk-13-13~17/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java openjdk-13-13~18/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java --- openjdk-13-13~17/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @bug 8087112 + * @bug 8087112 8222527 * @summary this test verifies that a client may provides authorization * headers directly when connecting with a server over SSL, and * it verifies that the client honor the jdk.http.auth.*.disabledSchemes @@ -45,10 +45,12 @@ * @run main/othervm/timeout=300 * -Djdk.http.auth.proxying.disabledSchemes=Basic * -Djdk.http.auth.tunneling.disabledSchemes=Basic + * -Dtest.requiresHost=true * ProxyAuthDisabledSchemesSSL SSL PROXY * @run main/othervm/timeout=300 * -Djdk.http.auth.proxying.disabledSchemes=Digest * -Djdk.http.auth.tunneling.disabledSchemes=Digest + * -Dtest.requiresHost=true * ProxyAuthDisabledSchemesSSL SSL PROXY */ diff -Nru openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/Client.java openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/Client.java --- openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/Client.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/Client.java 2019-04-24 19:25:41.000000000 +0000 @@ -118,15 +118,15 @@ String serverName = System.getProperty(Utils.PROP_SERVER_NAME); String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS); boolean supportsSNIOnServer - = Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_SERVER); + = Boolean.getBoolean(Utils.PROP_SUPPORTS_SNI_ON_SERVER); boolean supportsSNIOnClient - = Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_CLIENT); + = Boolean.getBoolean(Utils.PROP_SUPPORTS_SNI_ON_CLIENT); boolean supportsALPNOnServer - = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER); + = Boolean.getBoolean(Utils.PROP_SUPPORTS_ALPN_ON_SERVER); boolean supportsALPNOnClient - = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT); + = Boolean.getBoolean(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT); boolean negativeCase - = Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_CLIENT); + = Boolean.getBoolean(Utils.PROP_NEGATIVE_CASE_ON_CLIENT); System.out.println(Utils.join(Utils.PARAM_DELIMITER, "ClientJDK=" + System.getProperty(Utils.PROP_CLIENT_JDK), "Protocol=" + protocol, diff -Nru openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/Compatibility.java openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/Compatibility.java --- openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/Compatibility.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/Compatibility.java 2019-04-24 19:25:41.000000000 +0000 @@ -57,20 +57,33 @@ public class Compatibility { - public static void main(String[] args) throws Throwable { - String javaSecurityFile - = System.getProperty("test.src") + "/java.security"; - boolean debug = Utils.getBoolProperty("debug"); + protected List getUseCases() { + return UseCase.getAllUseCases(); + } - Set jdkInfos = jdkInfoList(); + protected Set getJdkInfos() { + return jdkInfoList(); + } - System.out.println("Test start"); + protected List runTest() throws Exception { + Set jdkInfos = getJdkInfos(); List testCases = new ArrayList<>(); ExecutorService executor = Executors.newCachedThreadPool(); PrintStream origStdOut = System.out; PrintStream origStdErr = System.err; + boolean debug = Boolean.getBoolean("debug"); + + String securityPropertiesFile = System.getProperty( + "test.security.properties", + System.getProperty("test.src") + "/java.security"); + System.out.println("security properties: " + securityPropertiesFile); + + // If true, server and client CANNOT be a same JDK + boolean disallowSameEndpoint = Boolean.getBoolean("disallowSameEndpoint"); + System.out.println("disallowSameEndpoint: " + disallowSameEndpoint); + try (PrintStream printStream = new PrintStream( new FileOutputStream(Utils.TEST_LOG, true))) { System.setOut(printStream); @@ -79,13 +92,13 @@ System.out.println(Utils.startHtml()); System.out.println(Utils.startPre()); - for (UseCase useCase : UseCase.getAllUseCases()) { + for (UseCase useCase : getUseCases()) { for (JdkInfo serverJdk : jdkInfos) { Map props = new LinkedHashMap<>(); if (debug) { props.put("javax.net.debug", "all"); } - props.put("java.security.properties", javaSecurityFile); + props.put("java.security.properties", securityPropertiesFile); props.put(Utils.PROP_PROTOCOL, useCase.protocol.name); props.put(Utils.PROP_CIPHER_SUITE, useCase.cipherSuite.name()); @@ -105,6 +118,10 @@ serverJdk.supportsALPN + ""); for (JdkInfo clientJdk : jdkInfos) { + if (disallowSameEndpoint && clientJdk == serverJdk) { + continue; + } + TestCase testCase = new TestCase(serverJdk, clientJdk, useCase); System.out.println(Utils.anchorName(testCase.toString(), @@ -162,16 +179,75 @@ System.setErr(origStdErr); executor.shutdown(); + return testCases; + } + + // Generates the test result report. + protected boolean generateReport(List testCases) + throws IOException { + boolean failed = false; + StringBuilder report = new StringBuilder(); + report.append(Utils.startHtml()); + report.append(Utils.tableStyle()); + report.append(Utils.startTable()); + report.append(Utils.row( + "No.", + "ServerJDK", + "ClientJDK", + "Protocol", + "CipherSuite", + "ClientAuth", + "SNI", + "ALPN", + "Status")); + for (int i = 0, size = testCases.size(); i < size; i++) { + TestCase testCase = testCases.get(i); + + report.append(Utils.row( + Utils.anchorLink( + Utils.TEST_LOG, + testCase.toString(), + i + ""), + testCase.serverJdk.version, + testCase.clientJdk.version, + testCase.useCase.protocol.name, + testCase.useCase.cipherSuite, + Utils.boolToStr( + testCase.useCase.clientAuth), + Utils.boolToStr( + testCase.useCase.serverName == UseCase.ServerName.EXAMPLE), + Utils.boolToStr( + testCase.useCase.appProtocol == UseCase.AppProtocol.EXAMPLE), + testCase.getStatus())); + failed = failed + || testCase.getStatus() == Status.FAIL + || testCase.getStatus() == Status.UNEXPECTED_SUCCESS; + } + report.append(Utils.endTable()); + report.append(Utils.endHtml()); + + generateFile("report.html", report.toString()); + return failed; + } + + protected void run() throws Exception { + System.out.println("Test start"); + List testCases= runTest(); System.out.println("Test end"); - System.out.println("Report is being generated..."); + boolean failed = generateReport(testCases); - System.out.println("Report is generated."); + System.out.println("Report was generated."); + if (failed) { throw new RuntimeException("At least one case failed. " + "Please check logs for more details."); } } + public static void main(String[] args) throws Throwable { + new Compatibility().run();; + } + private static Status getStatus(String log) { if (log.contains(Status.UNEXPECTED_SUCCESS.name())) { return Status.UNEXPECTED_SUCCESS; @@ -203,13 +279,10 @@ } // Retrieves JDK info from the file which is specified by jdkListFile. - // If no such file or no JDK is specified by the file, the current testing - // JDK will be used. - private static Set jdkInfoList() throws Throwable { - List jdkList = jdkList("jdkListFile"); - if (jdkList.size() == 0) { - jdkList.add(System.getProperty("test.jdk")); - } + // And the current testing JDK, which is specified by test.jdk, always be used. + private static Set jdkInfoList() { + List jdkList = jdkList(); + jdkList.add(System.getProperty("test.jdk")); Set jdkInfoList = new LinkedHashSet<>(); for (String jdkPath : jdkList) { @@ -222,14 +295,16 @@ return jdkInfoList; } - private static List jdkList(String listFileProp) throws IOException { - String listFile = System.getProperty(listFileProp); - System.out.println(listFileProp + "=" + listFile); + private static List jdkList() { + String listFile = System.getProperty("jdkListFile"); + System.out.println("jdk list file: " + listFile); if (listFile != null && Files.exists(Paths.get(listFile))) { try (Stream lines = Files.lines(Paths.get(listFile))) { return lines.filter(line -> { return !line.trim().isEmpty(); }).collect(Collectors.toList()); + } catch (IOException e) { + throw new RuntimeException("Cannot get jdk list", e); } } else { return new ArrayList<>(); @@ -273,54 +348,6 @@ return ProcessUtils.java(jdkPath, props, Client.class); } - // Generates the test result report. - private static boolean generateReport(List testCases) - throws IOException { - boolean failed = false; - StringBuilder report = new StringBuilder(); - report.append(Utils.startHtml()); - report.append(Utils.tableStyle()); - report.append(Utils.startTable()); - report.append(Utils.row( - "No.", - "ServerJDK", - "ClientJDK", - "Protocol", - "CipherSuite", - "ClientAuth", - "SNI", - "ALPN", - "Status")); - for (int i = 0, size = testCases.size(); i < size; i++) { - TestCase testCase = testCases.get(i); - - report.append(Utils.row( - Utils.anchorLink( - Utils.TEST_LOG, - testCase.toString(), - i + ""), - testCase.serverJdk.version, - testCase.clientJdk.version, - testCase.useCase.protocol.name, - testCase.useCase.cipherSuite, - Utils.boolToStr( - testCase.useCase.clientAuth), - Utils.boolToStr( - testCase.useCase.serverName == UseCase.ServerName.EXAMPLE), - Utils.boolToStr( - testCase.useCase.appProtocol == UseCase.AppProtocol.EXAMPLE), - testCase.getStatus())); - failed = failed - || testCase.getStatus() == Status.FAIL - || testCase.getStatus() == Status.UNEXPECTED_SUCCESS; - } - report.append(Utils.endTable()); - report.append(Utils.endHtml()); - - generateFile("report.html", report.toString()); - return failed; - } - private static void generateFile(String path, String content) throws IOException { try(FileWriter writer = new FileWriter(new File(path))) { diff -Nru openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/JdkInfo.java openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/JdkInfo.java --- openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/JdkInfo.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/JdkInfo.java 2019-04-24 19:25:41.000000000 +0000 @@ -36,7 +36,7 @@ public final boolean supportsSNI; public final boolean supportsALPN; - public JdkInfo(String jdkPath) throws Throwable { + public JdkInfo(String jdkPath) { this.jdkPath = jdkPath; String output = jdkAttributes(jdkPath); @@ -54,7 +54,7 @@ } // Determines the specific attributes for the specified JDK. - private static String jdkAttributes(String jdkPath) throws Throwable { + private static String jdkAttributes(String jdkPath) { return ProcessUtils.java(jdkPath, null, JdkUtils.class).getOutput(); } diff -Nru openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/Server.java openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/Server.java --- openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/Server.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/Server.java 2019-04-24 19:25:41.000000000 +0000 @@ -103,12 +103,12 @@ String protocol = System.getProperty(Utils.PROP_PROTOCOL); String cipherSuite = System.getProperty(Utils.PROP_CIPHER_SUITE); boolean clientAuth - = Utils.getBoolProperty(Utils.PROP_CLIENT_AUTH); + = Boolean.getBoolean(Utils.PROP_CLIENT_AUTH); String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS); boolean supportsALPN - = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER); + = Boolean.getBoolean(Utils.PROP_SUPPORTS_ALPN_ON_SERVER); boolean negativeCase - = Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_SERVER); + = Boolean.getBoolean(Utils.PROP_NEGATIVE_CASE_ON_SERVER); System.out.println(Utils.join(Utils.PARAM_DELIMITER, "ServerJDK=" + System.getProperty(Utils.PROP_SERVER_JDK), diff -Nru openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/UseCase.java openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/UseCase.java --- openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/UseCase.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/UseCase.java 2019-04-24 19:25:41.000000000 +0000 @@ -30,10 +30,10 @@ public class UseCase { private static final boolean FULL_CASES - = Utils.getBoolProperty("fullCases"); + = Boolean.getBoolean("fullCases"); public static final boolean FULL_CIPHER_SUITES - = Utils.getBoolProperty("fullCipherSuites"); + = Boolean.getBoolean("fullCipherSuites"); public static final Protocol[] PROTOCOLS = new Protocol[] { Protocol.TLSV1, @@ -129,7 +129,7 @@ } private static final Object[][] PARAMS = new Object[][] { - FULL_CASES ? PROTOCOLS : PROTOCOLS, + PROTOCOLS, FULL_CASES ? CIPHER_SUITES : MANDATORY_CIPHER_SUITES, FULL_CASES ? new Boolean[] { false, true } : new Boolean[] { true }, FULL_CASES diff -Nru openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/Utils.java openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/Utils.java --- openjdk-13-13~17/test/jdk/javax/net/ssl/compatibility/Utils.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/javax/net/ssl/compatibility/Utils.java 2019-04-24 19:25:41.000000000 +0000 @@ -166,10 +166,6 @@ return bool ? "Y" : "N"; } - public static boolean getBoolProperty(String prop) { - return Boolean.valueOf(System.getProperty(prop)); - } - public static Status handleException(Exception exception, boolean negativeCase) { Status status; diff -Nru openjdk-13-13~17/test/jdk/ProblemList.txt openjdk-13-13~18/test/jdk/ProblemList.txt --- openjdk-13-13~17/test/jdk/ProblemList.txt 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/ProblemList.txt 2019-04-24 19:25:41.000000000 +0000 @@ -240,6 +240,14 @@ java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucentWindowClick.java 8013450 macosx-all java/awt/Window/ShapedAndTranslucentWindows/StaticallyShaped.java 8165218 macosx-all,linux-all java/awt/Window/ShapedAndTranslucentWindows/TranslucentChoice.java 8221901 linux-all +java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java 8222323 windows-all +java/awt/Window/AlwaysOnTop/AutoTestOnTop.java 6847593 windows-all,linux-all +java/awt/Window/ShapedAndTranslucentWindows/FocusAWTTest.java 8222328 windows-all,linux-all +java/awt/Window/ShapedAndTranslucentWindows/Shaped.java 8222328 windows-all,linux-all +java/awt/Window/ShapedAndTranslucentWindows/ShapedByAPI.java 8222328 windows-all,linux-all +java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucent.java 8222328 windows-all,linux-all +java/awt/Window/ShapedAndTranslucentWindows/StaticallyShaped.java 8222328 windows-all +java/awt/Window/ShapedAndTranslucentWindows/Translucent.java 8222328 windows-all,linux-all,macosx-all java/awt/Window/AlwaysOnTop/AutoTestOnTop.java 6847593 macosx-all java/awt/Window/GrabSequence/GrabSequence.java 6848409 macosx-all,linux-all java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java 8203371 linux-all,solaris-all @@ -264,7 +272,7 @@ sun/java2d/DirectX/RenderingToCachedGraphicsTest/RenderingToCachedGraphicsTest.java 8196180 windows-all,macosx-all sun/java2d/GdiRendering/InsetClipping.java 8196181 windows-all java/awt/Graphics2D/CopyAreaOOB.java 7001973 windows-all,macosx-all -sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all +sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all,linux-all sun/java2d/SunGraphics2D/DrawImageBilinear.java 8191406 generic-all sun/java2d/SunGraphics2D/PolyVertTest.java 6986565 generic-all sun/java2d/SunGraphics2D/SimplePrimQuality.java 6992007 generic-all @@ -715,7 +723,6 @@ sun/security/pkcs11/tls/TestMasterSecret.java 8204203 windows-all sun/security/pkcs11/tls/TestPRF.java 8204203 windows-all sun/security/pkcs11/tls/TestPremaster.java 8204203 windows-all -sun/security/pkcs11/tls/tls12/TestTLS12.java 8221271 windows-all sun/security/tools/keytool/NssTest.java 8204203 windows-all ############################################################################ diff -Nru openjdk-13-13~17/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java openjdk-13-13~18/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java --- openjdk-13-13~17/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8029661 + * @summary Test TLS 1.2 + * @modules java.base/sun.security.internal.spec + * java.base/sun.security.util + * java.base/com.sun.crypto.provider + * @library /test/lib ../.. + * @run main/othervm/timeout=120 -Djdk.tls.useExtendedMasterSecret=false FipsModeTLS12 + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.nio.ByteBuffer; + +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManagerFactory; + +import sun.security.internal.spec.TlsMasterSecretParameterSpec; +import sun.security.internal.spec.TlsPrfParameterSpec; +import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; + +public final class FipsModeTLS12 extends SecmodTest { + + private static final boolean enableDebug = true; + + private static Provider sunPKCS11NSSProvider; + private static Provider sunJCEProvider; + private static KeyStore ks; + private static KeyStore ts; + private static char[] passphrase = "JAHshj131@@".toCharArray(); + private static PrivateKey privateKey; + private static PublicKey publicKey; + + public static void main(String[] args) throws Exception { + try { + initialize(); + } catch (Exception e) { + System.out.println("Test skipped: failure during" + + " initialization"); + if (enableDebug) { + System.out.println(e); + } + return; + } + + if (shouldRun()) { + // Test against JCE + testTlsAuthenticationCodeGeneration(); + + // Self-integrity test (complete TLS 1.2 communication) + new testTLS12SunPKCS11Communication().run(); + + System.out.println("Test PASS - OK"); + } else { + System.out.println("Test skipped: TLS 1.2 mechanisms" + + " not supported by current SunPKCS11 back-end"); + } + } + + private static boolean shouldRun() { + if (sunPKCS11NSSProvider == null) { + return false; + } + try { + KeyGenerator.getInstance("SunTls12MasterSecret", + sunPKCS11NSSProvider); + KeyGenerator.getInstance( + "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider); + KeyGenerator.getInstance("SunTls12Prf", sunPKCS11NSSProvider); + } catch (NoSuchAlgorithmException e) { + return false; + } + return true; + } + + private static void testTlsAuthenticationCodeGeneration() + throws Exception { + // Generate RSA Pre-Master Secret in SunPKCS11 provider + SecretKey rsaPreMasterSecret = null; + @SuppressWarnings("deprecation") + TlsRsaPremasterSecretParameterSpec rsaPreMasterSecretSpec = + new TlsRsaPremasterSecretParameterSpec(0x0303, 0x0303); + { + KeyGenerator rsaPreMasterSecretKG = KeyGenerator.getInstance( + "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider); + rsaPreMasterSecretKG.init(rsaPreMasterSecretSpec, null); + rsaPreMasterSecret = rsaPreMasterSecretKG.generateKey(); + } + + // Get RSA Pre-Master Secret in plain (from SunPKCS11 provider) + byte[] rsaPlainPreMasterSecret = null; + { + Cipher rsaPreMasterSecretWrapperCipher = + Cipher.getInstance("RSA/ECB/PKCS1Padding", + sunPKCS11NSSProvider); + rsaPreMasterSecretWrapperCipher.init(Cipher.WRAP_MODE, publicKey, + new SecureRandom()); + byte[] rsaEncryptedPreMasterSecret = + rsaPreMasterSecretWrapperCipher.wrap(rsaPreMasterSecret); + Cipher rsaPreMasterSecretUnwrapperCipher = + Cipher.getInstance("RSA/ECB/PKCS1Padding", sunJCEProvider); + rsaPreMasterSecretUnwrapperCipher.init(Cipher.UNWRAP_MODE, + privateKey, rsaPreMasterSecretSpec); + rsaPlainPreMasterSecret = rsaPreMasterSecretUnwrapperCipher.unwrap( + rsaEncryptedPreMasterSecret, "TlsRsaPremasterSecret", + Cipher.SECRET_KEY).getEncoded(); + + if (enableDebug) { + System.out.println("rsaPlainPreMasterSecret:"); + for (byte b : rsaPlainPreMasterSecret) { + System.out.printf("%02X, ", b); + } + System.out.println(""); + } + } + + // Generate Master Secret + SecretKey sunPKCS11MasterSecret = null; + SecretKey jceMasterSecret = null; + { + KeyGenerator sunPKCS11MasterSecretGenerator = + KeyGenerator.getInstance("SunTls12MasterSecret", + sunPKCS11NSSProvider); + KeyGenerator jceMasterSecretGenerator = KeyGenerator.getInstance( + "SunTls12MasterSecret", sunJCEProvider); + @SuppressWarnings("deprecation") + TlsMasterSecretParameterSpec sunPKCS11MasterSecretSpec = + new TlsMasterSecretParameterSpec(rsaPreMasterSecret, 3, 3, + new byte[32], new byte[32], "SHA-256", 32, 64); + @SuppressWarnings("deprecation") + TlsMasterSecretParameterSpec jceMasterSecretSpec = + new TlsMasterSecretParameterSpec( + new SecretKeySpec(rsaPlainPreMasterSecret, + "Generic"), 3, 3, new byte[32], + new byte[32], "SHA-256", 32, 64); + sunPKCS11MasterSecretGenerator.init(sunPKCS11MasterSecretSpec, + null); + jceMasterSecretGenerator.init(jceMasterSecretSpec, null); + sunPKCS11MasterSecret = + sunPKCS11MasterSecretGenerator.generateKey(); + jceMasterSecret = jceMasterSecretGenerator.generateKey(); + if (enableDebug) { + System.out.println("Master Secret (SunJCE):"); + if (jceMasterSecret != null) { + for (byte b : jceMasterSecret.getEncoded()) { + System.out.printf("%02X, ", b); + } + System.out.println(""); + } + } + } + + // Generate authentication codes + byte[] sunPKCS11AuthenticationCode = null; + byte[] jceAuthenticationCode = null; + { + // Generate SunPKCS11 authentication code + { + @SuppressWarnings("deprecation") + TlsPrfParameterSpec sunPKCS11AuthenticationCodeSpec = + new TlsPrfParameterSpec(sunPKCS11MasterSecret, + "client finished", "a".getBytes(), 12, + "SHA-256", 32, 64); + KeyGenerator sunPKCS11AuthCodeGenerator = + KeyGenerator.getInstance("SunTls12Prf", + sunPKCS11NSSProvider); + sunPKCS11AuthCodeGenerator.init( + sunPKCS11AuthenticationCodeSpec); + sunPKCS11AuthenticationCode = + sunPKCS11AuthCodeGenerator.generateKey().getEncoded(); + } + + // Generate SunJCE authentication code + { + @SuppressWarnings("deprecation") + TlsPrfParameterSpec jceAuthenticationCodeSpec = + new TlsPrfParameterSpec(jceMasterSecret, + "client finished", "a".getBytes(), 12, + "SHA-256", 32, 64); + KeyGenerator jceAuthCodeGenerator = + KeyGenerator.getInstance("SunTls12Prf", + sunJCEProvider); + jceAuthCodeGenerator.init(jceAuthenticationCodeSpec); + jceAuthenticationCode = + jceAuthCodeGenerator.generateKey().getEncoded(); + } + + if (enableDebug) { + System.out.println("SunPKCS11 Authentication Code: "); + for (byte b : sunPKCS11AuthenticationCode) { + System.out.printf("%02X, ", b); + } + System.out.println(""); + System.out.println("SunJCE Authentication Code: "); + for (byte b : jceAuthenticationCode) { + System.out.printf("%02X, ", b); + } + System.out.println(""); + } + } + + if (sunPKCS11AuthenticationCode == null || + jceAuthenticationCode == null || + sunPKCS11AuthenticationCode.length == 0 || + jceAuthenticationCode.length == 0 || + !Arrays.equals(sunPKCS11AuthenticationCode, + jceAuthenticationCode)) { + throw new Exception("Authentication codes from JCE" + + " and SunPKCS11 differ."); + } + } + + private static class testTLS12SunPKCS11Communication { + public static void run() throws Exception { + SSLEngine[][] enginesToTest = getSSLEnginesToTest(); + + for (SSLEngine[] engineToTest : enginesToTest) { + + SSLEngine clientSSLEngine = engineToTest[0]; + SSLEngine serverSSLEngine = engineToTest[1]; + + // SSLEngine code based on RedhandshakeFinished.java + + boolean dataDone = false; + + ByteBuffer clientOut = null; + ByteBuffer clientIn = null; + ByteBuffer serverOut = null; + ByteBuffer serverIn = null; + ByteBuffer cTOs; + ByteBuffer sTOc; + + SSLSession session = clientSSLEngine.getSession(); + int appBufferMax = session.getApplicationBufferSize(); + int netBufferMax = session.getPacketBufferSize(); + + clientIn = ByteBuffer.allocate(appBufferMax + 50); + serverIn = ByteBuffer.allocate(appBufferMax + 50); + + cTOs = ByteBuffer.allocateDirect(netBufferMax); + sTOc = ByteBuffer.allocateDirect(netBufferMax); + + clientOut = ByteBuffer.wrap( + "Hi Server, I'm Client".getBytes()); + serverOut = ByteBuffer.wrap( + "Hello Client, I'm Server".getBytes()); + + SSLEngineResult clientResult; + SSLEngineResult serverResult; + + while (!dataDone) { + clientResult = clientSSLEngine.wrap(clientOut, cTOs); + runDelegatedTasks(clientResult, clientSSLEngine); + serverResult = serverSSLEngine.wrap(serverOut, sTOc); + runDelegatedTasks(serverResult, serverSSLEngine); + cTOs.flip(); + sTOc.flip(); + + if (enableDebug) { + System.out.println("Client -> Network"); + printTlsNetworkPacket("", cTOs); + System.out.println(""); + System.out.println("Server -> Network"); + printTlsNetworkPacket("", sTOc); + System.out.println(""); + } + + clientResult = clientSSLEngine.unwrap(sTOc, clientIn); + runDelegatedTasks(clientResult, clientSSLEngine); + serverResult = serverSSLEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverResult, serverSSLEngine); + + cTOs.compact(); + sTOc.compact(); + + if (!dataDone && + (clientOut.limit() == serverIn.position()) && + (serverOut.limit() == clientIn.position())) { + checkTransfer(serverOut, clientIn); + checkTransfer(clientOut, serverIn); + dataDone = true; + } + } + } + } + + static void printTlsNetworkPacket(String prefix, ByteBuffer bb) { + ByteBuffer slice = bb.slice(); + byte[] buffer = new byte[slice.remaining()]; + slice.get(buffer); + for (int i = 0; i < buffer.length; i++) { + System.out.printf("%02X, ", (byte)(buffer[i] & (byte)0xFF)); + if (i % 8 == 0 && i % 16 != 0) { + System.out.print(" "); + } + if (i % 16 == 0) { + System.out.println(""); + } + } + System.out.flush(); + } + + private static void checkTransfer(ByteBuffer a, ByteBuffer b) + throws Exception { + a.flip(); + b.flip(); + if (!a.equals(b)) { + throw new Exception("Data didn't transfer cleanly"); + } + a.position(a.limit()); + b.position(b.limit()); + a.limit(a.capacity()); + b.limit(b.capacity()); + } + + private static void runDelegatedTasks(SSLEngineResult result, + SSLEngine engine) throws Exception { + + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + runnable.run(); + } + HandshakeStatus hsStatus = engine.getHandshakeStatus(); + if (hsStatus == HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + } + } + + private static SSLEngine[][] getSSLEnginesToTest() throws Exception { + SSLEngine[][] enginesToTest = new SSLEngine[2][2]; + String[][] preferredSuites = new String[][]{ new String[] { + "TLS_RSA_WITH_AES_128_CBC_SHA256" + }, new String[] { + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" + }}; + for (int i = 0; i < enginesToTest.length; i++) { + enginesToTest[i][0] = createSSLEngine(true); + enginesToTest[i][1] = createSSLEngine(false); + enginesToTest[i][0].setEnabledCipherSuites(preferredSuites[i]); + enginesToTest[i][1].setEnabledCipherSuites(preferredSuites[i]); + } + return enginesToTest; + } + + static private SSLEngine createSSLEngine(boolean client) + throws Exception { + SSLEngine ssle; + KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX", "SunJSSE"); + kmf.init(ks, passphrase); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE"); + tmf.init(ts); + + SSLContext sslCtx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); + sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + ssle = sslCtx.createSSLEngine("localhost", 443); + ssle.setUseClientMode(client); + SSLParameters sslParameters = ssle.getSSLParameters(); + ssle.setSSLParameters(sslParameters); + + return ssle; + } + } + + private static void initialize() throws Exception { + // + // For a successful FIPS-mode TLS connection, the following + // cryptographic providers will be installed: + // + // 1. SunPKCS11 (with an NSS FIPS mode backend) + // 2. SUN (to handle X.509 certificates) + // 3. SunJSSE (for a TLS engine) + // + // RSASSA-PSS algorithm is not currently supported in SunPKCS11 + // but in SUN provider. As a result, it can be negotiated by the + // TLS engine. The problem is that SunPKCS11 keys are sensitive + // in FIPS mode and cannot be used in a SUN algorithm (conversion + // fails as plain values cannot be extracted). + // + // To workaround this issue, we disable RSASSA-PSS algorithm for + // TLS connections. Once JDK-8222937 is fixed, this workaround can + // (and should) be removed. + // + // On a final note, the list of disabled TLS algorithms + // (jdk.tls.disabledAlgorithms) has to be updated at this point, + // before it is read in sun.security.ssl.SSLAlgorithmConstraints + // class initialization. + String disabledAlgorithms = + Security.getProperty("jdk.tls.disabledAlgorithms"); + if (disabledAlgorithms.length() > 0) { + disabledAlgorithms += ", "; + } + disabledAlgorithms += "RSASSA-PSS"; + Security.setProperty("jdk.tls.disabledAlgorithms", disabledAlgorithms); + + if (initSecmod() == false) { + return; + } + String configName = BASE + SEP + "nss.cfg"; + sunPKCS11NSSProvider = getSunPKCS11(configName); + System.out.println("SunPKCS11 provider: " + sunPKCS11NSSProvider); + + List installedProviders = new LinkedList<>(); + for (Provider p : Security.getProviders()){ + installedProviders.add(p); + Security.removeProvider(p.getName()); + } + Security.addProvider(sunPKCS11NSSProvider); + for (Provider p : installedProviders){ + String providerName = p.getName(); + if (providerName.equals("SunJSSE") || + providerName.equals("SUN") || + providerName.equals("SunJCE")) { + Security.addProvider(p); + if (providerName.equals("SunJCE")) { + sunJCEProvider = p; + } + } + } + + ks = KeyStore.getInstance("PKCS11", sunPKCS11NSSProvider); + ks.load(null, "test12".toCharArray()); + ts = ks; + + KeyStore ksPlain = readTestKeyStore(); + privateKey = (PrivateKey)ksPlain.getKey("rh_rsa_sha256", + passphrase); + publicKey = (PublicKey)ksPlain.getCertificate( + "rh_rsa_sha256").getPublicKey(); + } + + private static KeyStore readTestKeyStore() throws Exception { + File file = new File(System.getProperty("test.src", "."), "keystore"); + InputStream in = new FileInputStream(file); + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(in, "passphrase".toCharArray()); + in.close(); + return ks; + } +} diff -Nru openjdk-13-13~17/test/jdk/sun/security/pkcs11/tls/tls12/TestTLS12.java openjdk-13-13~18/test/jdk/sun/security/pkcs11/tls/tls12/TestTLS12.java --- openjdk-13-13~17/test/jdk/sun/security/pkcs11/tls/tls12/TestTLS12.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/jdk/sun/security/pkcs11/tls/tls12/TestTLS12.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,474 +0,0 @@ -/* - * Copyright (c) 2019, Red Hat, Inc. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8029661 - * @summary Test TLS 1.2 - * @modules java.base/sun.security.internal.spec - * java.base/sun.security.util - * java.base/com.sun.crypto.provider - * @library /test/lib ../.. - * @run main/othervm/timeout=120 TestTLS12 - */ - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.nio.ByteBuffer; - -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.SecureRandom; -import java.security.Security; - -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; - -import javax.crypto.Cipher; -import javax.crypto.KeyGenerator; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManagerFactory; - -import sun.security.internal.spec.TlsMasterSecretParameterSpec; -import sun.security.internal.spec.TlsPrfParameterSpec; -import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; - -public final class TestTLS12 extends SecmodTest { - - private static final boolean enableDebug = true; - - private static Provider sunPKCS11NSSProvider; - private static Provider sunJCEProvider; - private static KeyStore ks; - private static KeyStore ts; - private static char[] passphrase = "JAHshj131@@".toCharArray(); - private static RSAPrivateKey privateKey; - private static RSAPublicKey publicKey; - - public static void main(String[] args) throws Exception { - try { - initialize(); - } catch (Exception e) { - System.out.println("Test skipped: failure during" + - " initialization"); - if (enableDebug) { - System.out.println(e); - } - return; - } - - if (shouldRun()) { - // Test against JCE - testTlsAuthenticationCodeGeneration(); - - // Self-integrity test (complete TLS 1.2 communication) - new testTLS12SunPKCS11Communication().run(); - - System.out.println("Test PASS - OK"); - } else { - System.out.println("Test skipped: TLS 1.2 mechanisms" + - " not supported by current SunPKCS11 back-end"); - } - } - - private static boolean shouldRun() { - if (sunPKCS11NSSProvider == null) { - return false; - } - try { - KeyGenerator.getInstance("SunTls12MasterSecret", - sunPKCS11NSSProvider); - KeyGenerator.getInstance( - "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider); - KeyGenerator.getInstance("SunTls12Prf", sunPKCS11NSSProvider); - } catch (NoSuchAlgorithmException e) { - return false; - } - return true; - } - - private static void testTlsAuthenticationCodeGeneration() - throws Exception { - // Generate RSA Pre-Master Secret in SunPKCS11 provider - SecretKey rsaPreMasterSecret = null; - @SuppressWarnings("deprecation") - TlsRsaPremasterSecretParameterSpec rsaPreMasterSecretSpec = - new TlsRsaPremasterSecretParameterSpec(0x0303, 0x0303); - { - KeyGenerator rsaPreMasterSecretKG = KeyGenerator.getInstance( - "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider); - rsaPreMasterSecretKG.init(rsaPreMasterSecretSpec, null); - rsaPreMasterSecret = rsaPreMasterSecretKG.generateKey(); - } - - // Get RSA Pre-Master Secret in plain (from SunPKCS11 provider) - byte[] rsaPlainPreMasterSecret = null; - { - Cipher rsaPreMasterSecretWrapperCipher = - Cipher.getInstance("RSA/ECB/PKCS1Padding", - sunPKCS11NSSProvider); - rsaPreMasterSecretWrapperCipher.init(Cipher.WRAP_MODE, publicKey, - new SecureRandom()); - byte[] rsaEncryptedPreMasterSecret = - rsaPreMasterSecretWrapperCipher.wrap(rsaPreMasterSecret); - Cipher rsaPreMasterSecretUnwrapperCipher = - Cipher.getInstance("RSA/ECB/PKCS1Padding", sunJCEProvider); - rsaPreMasterSecretUnwrapperCipher.init(Cipher.UNWRAP_MODE, - privateKey, rsaPreMasterSecretSpec); - rsaPlainPreMasterSecret = rsaPreMasterSecretUnwrapperCipher.unwrap( - rsaEncryptedPreMasterSecret, "TlsRsaPremasterSecret", - Cipher.SECRET_KEY).getEncoded(); - - if (enableDebug) { - System.out.println("rsaPlainPreMasterSecret:"); - for (byte b : rsaPlainPreMasterSecret) { - System.out.printf("%02X, ", b); - } - System.out.println(""); - } - } - - // Generate Master Secret - SecretKey sunPKCS11MasterSecret = null; - SecretKey jceMasterSecret = null; - { - KeyGenerator sunPKCS11MasterSecretGenerator = - KeyGenerator.getInstance("SunTls12MasterSecret", - sunPKCS11NSSProvider); - KeyGenerator jceMasterSecretGenerator = KeyGenerator.getInstance( - "SunTls12MasterSecret", sunJCEProvider); - @SuppressWarnings("deprecation") - TlsMasterSecretParameterSpec sunPKCS11MasterSecretSpec = - new TlsMasterSecretParameterSpec(rsaPreMasterSecret, 3, 3, - new byte[32], new byte[32], "SHA-256", 32, 64); - @SuppressWarnings("deprecation") - TlsMasterSecretParameterSpec jceMasterSecretSpec = - new TlsMasterSecretParameterSpec( - new SecretKeySpec(rsaPlainPreMasterSecret, - "Generic"), 3, 3, new byte[32], - new byte[32], "SHA-256", 32, 64); - sunPKCS11MasterSecretGenerator.init(sunPKCS11MasterSecretSpec, - null); - jceMasterSecretGenerator.init(jceMasterSecretSpec, null); - sunPKCS11MasterSecret = - sunPKCS11MasterSecretGenerator.generateKey(); - jceMasterSecret = jceMasterSecretGenerator.generateKey(); - if (enableDebug) { - System.out.println("Master Secret (SunJCE):"); - if (jceMasterSecret != null) { - for (byte b : jceMasterSecret.getEncoded()) { - System.out.printf("%02X, ", b); - } - System.out.println(""); - } - } - } - - // Generate authentication codes - byte[] sunPKCS11AuthenticationCode = null; - byte[] jceAuthenticationCode = null; - { - // Generate SunPKCS11 authentication code - { - @SuppressWarnings("deprecation") - TlsPrfParameterSpec sunPKCS11AuthenticationCodeSpec = - new TlsPrfParameterSpec(sunPKCS11MasterSecret, - "client finished", "a".getBytes(), 12, - "SHA-256", 32, 64); - KeyGenerator sunPKCS11AuthCodeGenerator = - KeyGenerator.getInstance("SunTls12Prf", - sunPKCS11NSSProvider); - sunPKCS11AuthCodeGenerator.init( - sunPKCS11AuthenticationCodeSpec); - sunPKCS11AuthenticationCode = - sunPKCS11AuthCodeGenerator.generateKey().getEncoded(); - } - - // Generate SunJCE authentication code - { - @SuppressWarnings("deprecation") - TlsPrfParameterSpec jceAuthenticationCodeSpec = - new TlsPrfParameterSpec(jceMasterSecret, - "client finished", "a".getBytes(), 12, - "SHA-256", 32, 64); - KeyGenerator jceAuthCodeGenerator = - KeyGenerator.getInstance("SunTls12Prf", - sunJCEProvider); - jceAuthCodeGenerator.init(jceAuthenticationCodeSpec); - jceAuthenticationCode = - jceAuthCodeGenerator.generateKey().getEncoded(); - } - - if (enableDebug) { - System.out.println("SunPKCS11 Authentication Code: "); - for (byte b : sunPKCS11AuthenticationCode) { - System.out.printf("%02X, ", b); - } - System.out.println(""); - System.out.println("SunJCE Authentication Code: "); - for (byte b : jceAuthenticationCode) { - System.out.printf("%02X, ", b); - } - System.out.println(""); - } - } - - if (sunPKCS11AuthenticationCode == null || - jceAuthenticationCode == null || - sunPKCS11AuthenticationCode.length == 0 || - jceAuthenticationCode.length == 0 || - !Arrays.equals(sunPKCS11AuthenticationCode, - jceAuthenticationCode)) { - throw new Exception("Authentication codes from JCE" + - " and SunPKCS11 differ."); - } - } - - private static class testTLS12SunPKCS11Communication { - public static void run() throws Exception { - SSLEngine[][] enginesToTest = getSSLEnginesToTest(); - - for (SSLEngine[] engineToTest : enginesToTest) { - - SSLEngine clientSSLEngine = engineToTest[0]; - SSLEngine serverSSLEngine = engineToTest[1]; - - // SSLEngine code based on RedhandshakeFinished.java - - boolean dataDone = false; - - ByteBuffer clientOut = null; - ByteBuffer clientIn = null; - ByteBuffer serverOut = null; - ByteBuffer serverIn = null; - ByteBuffer cTOs; - ByteBuffer sTOc; - - SSLSession session = clientSSLEngine.getSession(); - int appBufferMax = session.getApplicationBufferSize(); - int netBufferMax = session.getPacketBufferSize(); - - clientIn = ByteBuffer.allocate(appBufferMax + 50); - serverIn = ByteBuffer.allocate(appBufferMax + 50); - - cTOs = ByteBuffer.allocateDirect(netBufferMax); - sTOc = ByteBuffer.allocateDirect(netBufferMax); - - clientOut = ByteBuffer.wrap( - "Hi Server, I'm Client".getBytes()); - serverOut = ByteBuffer.wrap( - "Hello Client, I'm Server".getBytes()); - - SSLEngineResult clientResult; - SSLEngineResult serverResult; - - while (!dataDone) { - clientResult = clientSSLEngine.wrap(clientOut, cTOs); - runDelegatedTasks(clientResult, clientSSLEngine); - serverResult = serverSSLEngine.wrap(serverOut, sTOc); - runDelegatedTasks(serverResult, serverSSLEngine); - cTOs.flip(); - sTOc.flip(); - - if (enableDebug) { - System.out.println("Client -> Network"); - printTlsNetworkPacket("", cTOs); - System.out.println(""); - System.out.println("Server -> Network"); - printTlsNetworkPacket("", sTOc); - System.out.println(""); - } - - clientResult = clientSSLEngine.unwrap(sTOc, clientIn); - runDelegatedTasks(clientResult, clientSSLEngine); - serverResult = serverSSLEngine.unwrap(cTOs, serverIn); - runDelegatedTasks(serverResult, serverSSLEngine); - - cTOs.compact(); - sTOc.compact(); - - if (!dataDone && - (clientOut.limit() == serverIn.position()) && - (serverOut.limit() == clientIn.position())) { - checkTransfer(serverOut, clientIn); - checkTransfer(clientOut, serverIn); - dataDone = true; - } - } - } - } - - static void printTlsNetworkPacket(String prefix, ByteBuffer bb) { - ByteBuffer slice = bb.slice(); - byte[] buffer = new byte[slice.remaining()]; - slice.get(buffer); - for (int i = 0; i < buffer.length; i++) { - System.out.printf("%02X, ", (byte)(buffer[i] & (byte)0xFF)); - if (i % 8 == 0 && i % 16 != 0) { - System.out.print(" "); - } - if (i % 16 == 0) { - System.out.println(""); - } - } - System.out.flush(); - } - - private static void checkTransfer(ByteBuffer a, ByteBuffer b) - throws Exception { - a.flip(); - b.flip(); - if (!a.equals(b)) { - throw new Exception("Data didn't transfer cleanly"); - } - a.position(a.limit()); - b.position(b.limit()); - a.limit(a.capacity()); - b.limit(b.capacity()); - } - - private static void runDelegatedTasks(SSLEngineResult result, - SSLEngine engine) throws Exception { - - if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { - Runnable runnable; - while ((runnable = engine.getDelegatedTask()) != null) { - runnable.run(); - } - HandshakeStatus hsStatus = engine.getHandshakeStatus(); - if (hsStatus == HandshakeStatus.NEED_TASK) { - throw new Exception( - "handshake shouldn't need additional tasks"); - } - } - } - - private static SSLEngine[][] getSSLEnginesToTest() throws Exception { - SSLEngine[][] enginesToTest = new SSLEngine[2][2]; - String[][] preferredSuites = new String[][]{ new String[] { - "TLS_RSA_WITH_AES_128_CBC_SHA256" - }, new String[] { - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" - }}; - for (int i = 0; i < enginesToTest.length; i++) { - enginesToTest[i][0] = createSSLEngine(true); - enginesToTest[i][1] = createSSLEngine(false); - enginesToTest[i][0].setEnabledCipherSuites(preferredSuites[i]); - enginesToTest[i][1].setEnabledCipherSuites(preferredSuites[i]); - } - return enginesToTest; - } - - static private SSLEngine createSSLEngine(boolean client) - throws Exception { - SSLEngine ssle; - KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX", "SunJSSE"); - kmf.init(ks, passphrase); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE"); - tmf.init(ts); - - SSLContext sslCtx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); - sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - ssle = sslCtx.createSSLEngine("localhost", 443); - ssle.setUseClientMode(client); - SSLParameters sslParameters = ssle.getSSLParameters(); - ssle.setSSLParameters(sslParameters); - - return ssle; - } - } - - private static void initialize() throws Exception { - if (initSecmod() == false) { - return; - } - String configName = BASE + SEP + "nss.cfg"; - sunPKCS11NSSProvider = getSunPKCS11(configName); - System.out.println("SunPKCS11 provider: " + sunPKCS11NSSProvider); - - List installedProviders = new LinkedList<>(); - for (Provider p : Security.getProviders()){ - installedProviders.add(p); - Security.removeProvider(p.getName()); - } - Security.addProvider(sunPKCS11NSSProvider); - for (Provider p : installedProviders){ - String providerName = p.getName(); - if (providerName.equals("SunJSSE") || - providerName.equals("SUN") || - providerName.equals("SunJCE")) { - Security.addProvider(p); - if (providerName.equals("SunJCE")) { - sunJCEProvider = p; - } - } - } - - ks = KeyStore.getInstance("PKCS11", sunPKCS11NSSProvider); - ks.load(null, "test12".toCharArray()); - ts = ks; - - KeyStore ksPlain = readTestKeyStore(); - privateKey = (RSAPrivateKey)ksPlain.getKey("rh_rsa_sha256", - passphrase); - publicKey = (RSAPublicKey)ksPlain.getCertificate( - "rh_rsa_sha256").getPublicKey(); - - // Extended Master Secret is not currently supported in SunPKCS11 - // cryptographic provider - System.setProperty("jdk.tls.useExtendedMasterSecret", "false"); - String disabledAlgorithms = - Security.getProperty("jdk.tls.disabledAlgorithms"); - if (disabledAlgorithms.length() > 0) { - disabledAlgorithms += ", "; - } - // RSASSA-PSS is not currently supported in SunPKCS11 - // cryptographic provider - disabledAlgorithms += "RSASSA-PSS"; - Security.setProperty("jdk.tls.disabledAlgorithms", disabledAlgorithms); - } - - private static KeyStore readTestKeyStore() throws Exception { - File file = new File(System.getProperty("test.src", "."), "keystore"); - InputStream in = new FileInputStream(file); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(in, "passphrase".toCharArray()); - in.close(); - return ks; - } -} diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java 2019-04-24 19:25:41.000000000 +0000 @@ -62,6 +62,9 @@ + "", "", "

DEFAULT_NAME

\n" + + "\n" + + "\n" + + "\n" + "
static final java."
                 + "lang.String DEFAULT_NAME
"); @@ -74,17 +77,20 @@ checkOutput("pkg/AnnotationType.html", true, "", "
    ", - "
  • ", + "
  • ", + "
    ", + "

    Element Detail

    ", + "
    ", "", "", - "

    Element Detail

    ", + "
      ", + "
    • ", + "
      ", + "

      value

      ", "", "", "", - "
        ", - "
      • ", - "

        value

        ", - "
        int value
        " ); + "
        int value
        "); checkOutput("pkg/AnnotationType.html", false, "
        \n\n" diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java 2019-04-24 19:25:41.000000000 +0000 @@ -68,10 +68,11 @@ "visibleMethod", "

        Nested classes/interfaces inherited from class pkg1." + "A

        \n" + - "" + + "\n" + + "\n" + + "" + "A.VisibleInner, A.VisibleInnerExtendsInvisibleInner
      • \n" + - "
      "); + "title=\"class in pkg1\">A.VisibleInnerExtendsInvisibleInner\n"); checkOutput("pkg1/A.VisibleInner.html", false, "../pkg1/A.VisibleInner.html#VisibleInner()", @@ -82,7 +83,7 @@ "
      public static class " +
                       "A.VisibleInnerExtendsInvisibleInner\n" +
                       "extends A
      ", - "visibleField
    • ", + "visibleField", "visibleMethod"); checkOutput("pkg1/A.VisibleInnerExtendsInvisibleInner.html", false, diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java 2019-04-24 19:25:41.000000000 +0000 @@ -375,10 +375,12 @@ checkOutput("pkg1/C1.html", expectFound, "
      public void readObject()\n" +
                       "                throws java.io.IOException
      \n" + + "
    \n" + "
  • "); checkOutput("pkg1/C2.html", expectFound, "
    public C2()
    \n" + + "\n" + ""); checkOutput("pkg1/C1.ModalExclusionType.html", expectFound, @@ -386,6 +388,7 @@ "static final C1.ModalExclusionType " + "APPLICATION_EXCLUDE\n" + + "\n" + ""); checkOutput("serialized-form.html", expectFound, diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java 2019-04-24 19:25:41.000000000 +0000 @@ -109,7 +109,7 @@ checkOutput("pkg3/package-summary.html", true, "
    \n" - + "
    \n" + + "
    \n" + "\n" + "\n" + "

    This is the first line. Note the newlines before the <p> is relevant.

    \n" diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java 2019-04-24 19:25:41.000000000 +0000 @@ -100,7 +100,7 @@ + "", "
    \n" + "
    ", - "
    \n" + "
    \n" + "\n" + "\n" + "
    Test package.
    ", @@ -110,6 +110,7 @@ // No package description checkOutput("pkg1/package-summary.html", true, "
    \n" + + "
    \n" + "
      \n" + "
    • \n" + "
      \n\n" @@ -129,13 +130,13 @@ + "", "
      \n" + "
      ", - "
      \n" + "
      \n" + "

      Class Hierarchy

      ", - "
      \n" + "
      \n" + "

      Interface Hierarchy

      ", - "
      \n" + "
      \n" + "

      Annotation Type Hierarchy

      ", - "
      \n" + "
      \n" + "

      Enum Hierarchy

      ", "
      \n" + "
      ", - "
      \n" - + "
      ", - "
      \n" - + "
      ", - "
      \n" - + "
      \n", - "
      \n" - + "
      ", - "
      \n" - + "
      \n", - "
      \n" - + "
      ", - "
      \n" - + "
      ", - "
      \n" - + "
      ", - "
      \n" + "
      \n" + "\n" + "\n" + "

      Uses of RegClass in pkg

      \n" @@ -569,7 +539,7 @@ + "\n" + "", "
      \n" - + "

      Package pkg Description

      \n", + + "

      Package pkg Description

      \n", "
      \n
      ", "
      \n
      ", "
      \n
      ", diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java 2019-04-24 19:25:41.000000000 +0000 @@ -132,6 +132,9 @@ checkOutput("pkg/ClassWithStaticMembers.html", true, "

      f

      \n" + + "\n" + + "\n" + + "\n" + "
      public static int f
      \n" + "
      A hider field
      ", @@ -143,6 +146,9 @@ + "\n", "

      staticMethod

      \n" + + "\n" + + "\n" + + "\n" + "
      public static void staticMethod()
      \n" + "
      \n" + "
      Defines if paused.
      ", "

      paused

      \n" + + "\n" + + "\n" + + "\n" + "
      public final C.BooleanProperty pausedProperty
      \n" + "
      Defines if paused. The second line.
      ", "

      isPaused

      \n" + + "\n" + + "\n" + + "\n" + "
      public final double isPaused()
      \n" + "
      Gets the value of the property paused.
      ", "

      setPaused

      \n" + + "\n" + + "\n" + + "\n" + "
      public final void setPaused​(boolean value)
      \n" + "
      Sets the value of the property paused.
      \n" + "
      \n" @@ -102,6 +111,9 @@ + "
      Default value:
      \n" + "
      false
      ", "

      isPaused

      \n" + + "\n" + + "\n" + + "\n" + "
      public final double isPaused()
      \n" + "
      Gets the value of the property paused.
      \n" + "
      \n" @@ -110,12 +122,18 @@ + "
      Default value:
      \n" + "
      false
      ", "

      rate

      \n" + + "\n" + + "\n" + + "\n" + "
      public final C.DoubleProperty rateProperty
      \n" + "
      Defines the direction/speed at which the " + "Timeline is expected to\n" + " be played. This is the second line.
      ", "

      setRate

      \n" + + "\n" + + "\n" + + "\n" + "
      public final void setRate​(double value)
      \n" + "
      Sets the value of the property rate.
      \n" + "
      \n" @@ -127,6 +145,9 @@ + "
      Since:
      \n" + "
      JavaFX 8.0
      ", "

      getRate

      \n" + + "\n" + + "\n" + + "\n" + "
      public final double getRate()
      \n" + "
      Gets the value of the property rate.
      \n" + "
      \n" @@ -170,8 +191,10 @@ checkOutput("pkg1/D.html", true, "

      Properties inherited from class pkg1." + "C

      \n" - + "" - + "paused, rate"); + + "\n" + + "\n" + + "" + + "paused, rate"); checkOutput("pkg1/D.html", false, "shouldNotAppear"); } @@ -191,36 +214,40 @@ checkExit(Exit.OK); checkOutput("pkg2/Test.html", true, "

      Property Detail

      \n" - + "\n" + + "\n" + "\n" + "\n" + "
        \n" + "
      • \n" + + "
        \n" + "

        beta

        \n" + + "\n" + + "\n" + + "\n" + "
        public java.lang.Object betaProperty
        \n" + + "
        \n" + "
      • \n" - + "
      \n" + + "
    • \n" + + "
      \n" + + "

      gamma

      \n" + "\n" + "\n" + "\n" - + "
        \n" - + "
      • \n" - + "

        gamma

        \n" + "
        public final java.util.List<java.lang.String> gammaProperty
        \n" + + "
      \n" + "
    • \n" - + "\n" + + "
    • \n" + + "
      \n" + + "

      delta

      \n" + "\n" + "\n" + "\n" - + "
        \n" - + "
      • \n" - + "

        delta

        \n" + "
        public final java.util.List<"
                         + "java.util.Set<? super java.lang.Object>> deltaProperty
        \n" + + "
      \n" + "
    • \n" + "\n" - + "\n" - + "", + + "", "

      Property Summary

      \n" + "
      \n\n" + ""); diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java 2019-04-24 19:25:41.000000000 +0000 @@ -23,7 +23,7 @@ /* * @test - * @bug 8195795 8201396 8196202 + * @bug 8195795 8201396 8196202 8215582 * @summary test the use of module directories in output, * and the --no-module-directories option * @modules jdk.javadoc/jdk.javadoc.internal.api @@ -76,32 +76,12 @@ .classes("package pa; public class A {}") .exports("pa") .write(src); - new ModuleBuilder(tb, "mb") - .classes("package pb; public class B {}") - .exports("pb") - .write(src); javadoc("-d", base.resolve("api").toString(), - "-quiet", "--module-source-path", src.toString(), "--no-module-directories", "--module", "ma,mb"); - - checkExit(Exit.OK); - checkFiles(true, - "ma-summary.html", - "pa/package-summary.html"); - checkFiles(false, - "ma/module-summary.html", - "ma/pa/package-summary.html"); - checkOutput("ma-summary.html", false, - "\n"); - checkOutput("pa/package-summary.html", true, - "
    • Deprecated
    • \n" - + "
    • Index
    • "); - + checkExit(Exit.ERROR); } @Test diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java 2019-04-24 19:25:41.000000000 +0000 @@ -478,7 +478,7 @@ void checkHtml5Description(boolean found) { checkOutput("moduleA/module-summary.html", found, - "
      \n" + "
      \n" + "
      Deprecated, for removal:" + " This API element is subject to removal in a future version.\n" + "
      This module is deprecated.
      \n" @@ -490,7 +490,7 @@ + "
      This is a test description for the moduleA module with a Search " + "phrase search phrase.
      "); checkOutput("moduleB/module-summary.html", found, - "
      \n" + "
      \n" + "\n" + "\n" + "\n" @@ -523,17 +523,17 @@ void checkHtml5NoDescription(boolean found) { checkOutput("moduleA/module-summary.html", found, "
      \n" + + "
      \n" + "
        \n" + "
      • \n" - + "
          \n" - + "
        • \n" + + "
          \n" + ""); checkOutput("moduleB/module-summary.html", found, "
          \n" + + "
          \n" + "
            \n" + "
          • \n" - + "
              \n" - + "
            • \n" + + "
              \n" + ""); } diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java 2019-04-24 19:25:41.000000000 +0000 @@ -193,10 +193,18 @@ "
              @Documented\npublic @interface "
                               + "AnnotationTypeField
              ", - "

              DEFAULT_NAME

              \n
              static final java.lang.String "
              +                "

              DEFAULT_NAME

              \n" + + "
              \n" + + "\n" + + "\n" + + "
              static final java.lang.String "
                               + ""
                               + "DEFAULT_NAME
              ", - "

              name

              \n
              java.lang.String name\n"
              +                + "\n"
              +                + "\n"
              +                + "\n"
              +                + "
              java.lang.String name
              "); checkOutput("src-html/linksource/AnnotationTypeField.html", true, diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java 2019-04-24 19:25:41.000000000 +0000 @@ -52,10 +52,13 @@ checkExit(Exit.OK); checkOutput("pkg4/Foo.html", true, - "
            • \n" + "
              \n" + "

              toString

              \n" + + "\n" + + "\n" + + "\n" + "
              public void toString()
              \n" + "
              Why can't I do this ?
              \n" - + "
            • "); + + "
              "); } } diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java 2019-04-24 19:25:41.000000000 +0000 @@ -291,22 +291,8 @@ } @Test - public void testNoModuleDirectories() { - javadoc("-d", "out-noMdlDir", - "--no-module-directories", - "-Xdoclint:none", - "-sourcepath", testSrc, - "-use", - "pkg", "pkg1", "pkg2", "pkg3"); - checkExit(Exit.OK); - checkSearchOutput(true, false); - checkSearchJS(); - } - - @Test public void testURLEncoding() { javadoc("-d", "out-encode-html5", - "--no-module-directories", "-Xdoclint:none", "-sourcepath", testSrc, "-use", @@ -320,7 +306,6 @@ public void testJapaneseLocale() { javadoc("-locale", "ja_JP", "-d", "out-jp", - "--no-module-directories", "-Xdoclint:none", "-sourcepath", testSrc, "-use", @@ -339,7 +324,6 @@ public void testChineseLocale() { javadoc("-locale", "zh_CN", "-d", "out-cn", - "--no-module-directories", "-Xdoclint:none", "-sourcepath", testSrc, "-use", @@ -396,10 +380,9 @@ "\n", "", "var pathtoroot = \"./\";\n" - + "var useModuleDirectories = " + moduleDirectoriesVar + ";\n" + "loadScripts(document, 'script');", - "
                \n", - "
              • \n" + "
                ", + "\n" + "\n" + "\n"); checkOutput(fileName, true, @@ -632,22 +615,20 @@ + " });", "function getURLPrefix(ui) {\n" + " var urlPrefix=\"\";\n" - + " if (useModuleDirectories) {\n" - + " var slash = \"/\";\n" - + " if (ui.item.category === catModules) {\n" - + " return ui.item.l + slash;\n" - + " } else if (ui.item.category === catPackages && ui.item.m) {\n" - + " return ui.item.m + slash;\n" - + " } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) {\n" - + " $.each(packageSearchIndex, function(index, item) {\n" - + " if (item.m && ui.item.p == item.l) {\n" - + " urlPrefix = item.m + slash;\n" - + " }\n" - + " });\n" - + " return urlPrefix;\n" - + " } else {\n" - + " return urlPrefix;\n" - + " }\n" + + " var slash = \"/\";\n" + + " if (ui.item.category === catModules) {\n" + + " return ui.item.l + slash;\n" + + " } else if (ui.item.category === catPackages && ui.item.m) {\n" + + " return ui.item.m + slash;\n" + + " } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) {\n" + + " $.each(packageSearchIndex, function(index, item) {\n" + + " if (item.m && ui.item.p == item.l) {\n" + + " urlPrefix = item.m + slash;\n" + + " }\n" + + " });\n" + + " return urlPrefix;\n" + + " } else {\n" + + " return urlPrefix;\n" + " }\n" + " return urlPrefix;\n" + "}", diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8219998 + * @summary Eliminate inherently singleton lists + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.javadoc/jdk.javadoc.internal.api + * jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox toolbox.JavacTask javadoc.tester.* + * @run main TestSingletonLists + */ + +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.TreeMap; +import java.util.function.Function; + +import javadoc.tester.HtmlChecker; +import javadoc.tester.JavadocTester; +import toolbox.ModuleBuilder; +import toolbox.ToolBox; + + +public class TestSingletonLists extends JavadocTester { + public static void main(String... args) throws Exception { + TestSingletonLists tester = new TestSingletonLists(); + tester.runTests(); + } + + enum Index { SINGLE, SPLIT }; + enum Source { PACKAGES, MODULES }; + + final ToolBox tb = new ToolBox(); + + public void runTests() throws Exception { + for (Source s : Source.values()) { + Path src = genSource(s); + for (Index i : Index.values()) { + List args = new ArrayList<>(); + args.add("-d"); + args.add(String.format("out-%s-%s", s, i)); + args.add("-use"); + if (s != Source.MODULES) { + args.add("-linksource"); // broken, with modules: JDK-8219060 + } + if (i == Index.SPLIT) { + args.add("-splitIndex"); + } + if (s == Source.PACKAGES) { + args.add("-sourcepath"); + args.add(src.toString()); + args.add("p1"); + args.add("p2"); + args.add("p3"); + } else { + args.add("--module-source-path"); + args.add(src.toString()); + args.add("--module"); + args.add("mA,mB,mC"); + } + javadoc(args.toArray(new String[args.size()])); + checkExit(Exit.OK); + checkLists(); + } + } + + printSummary(); + } + + Path genSource(Source s) throws IOException { + Path src = Path.of("src-" + s); + switch (s) { + case PACKAGES: + for (String p : new String[] { "1", "2", "3" }) { + tb.writeJavaFiles(src, genClasses("p" + p)); + } + break; + + case MODULES: + for (String m : new String[] { "A", "B", "C"}) { + ModuleBuilder mb = new ModuleBuilder(tb, "m" + m); + for (String p : new String[] { "1", "2", "3" } ) { + mb.exports("p" + m + p); + mb.classes(genClasses("p" + m + p)); + } + mb.write(src); + } + break; + } + + return src; + } + + + String[] genClasses(String pkg) { + List list = new ArrayList<>(); + list.add("package " + pkg + ";"); + for (int i = 0; i < 3; i++) { + list.add(genClass(pkg, i)); + list.add(genAnno(pkg, i)); + list.add(genEnum(pkg, i)); + } + return list.toArray(new String[list.size()]); + } + + String genClass(String pkg, int index) { + String cn = (pkg + "c" + index).toUpperCase(); + StringBuilder sb = new StringBuilder(); + int pkgIndex = Character.getNumericValue(pkg.charAt(pkg.length()-1)); + String pkgdependency = pkg.substring(0, pkg.length()-1) + (pkgIndex == 3 ? 1 : pkgIndex + 1); + String enumClassName = pkgdependency.toUpperCase() + "E" + index; + sb.append("package ").append(pkg).append(";\n") + .append("import " + pkgdependency + ".*;\n") + .append("public class ").append(cn).append(" {\n"); + // fields + for (int f = 0; f < 3; f++) { + sb.append("public int f").append(f).append(";\n"); + } + // constructors + for (int c = 0; c < 3; c++) { + sb.append("public ").append(cn).append("("); + for (int i = 0; i < c; i++) { + sb.append(i == 0 ? "" : ", ").append("int i").append(i); + } + sb.append(") { }\n"); + } + // methods + for (int m = 0; m < 3; m++) { + sb.append("public void m").append(m).append("() { }\n"); + } + sb.append("public void n(").append(enumClassName).append(" e){}"); + sb.append("}\n"); + return sb.toString(); + } + + String genAnno(String pkg, int index) { + String an = (pkg + "a" + index).toUpperCase(); + StringBuilder sb = new StringBuilder(); + sb.append("package ").append(pkg).append(";\n") + .append("public @interface ").append(an).append(" {\n"); + // fields + for (int f = 0; f < 3; f++) { + sb.append("public static final int f").append(f).append(" = 0;\n"); + } + // values + for (int v = 0; v < 6; v++) { + sb.append("public int v").append(v).append("()").append(v< 3 ? "" : " default " + v).append(";\n"); + } + sb.append("}\n"); + return sb.toString(); + } + + String genEnum(String pkg, int index) { + String en = (pkg + "e" + index).toUpperCase(); + StringBuilder sb = new StringBuilder(); + sb.append("package ").append(pkg).append(";\n") + .append("public enum ").append(en).append(" {\n"); + // enum members + for (int e = 0; e < 3; e++) { + sb.append(e == 0 ? "" : ", ").append("E").append(e); + } + sb.append(";\n"); + // fields + for (int f = 0; f < 3; f++) { + sb.append("public int f").append(f).append(";\n"); + } + // methods + for (int m = 0; m < 3; m++) { + sb.append("public void m").append(m).append("() { }\n"); + } + sb.append("}\n"); + return sb.toString(); + } + + void checkLists() { + checking("Check lists"); + ListChecker c = new ListChecker(out, this::readFile); + try { + c.checkDirectory(outputDir.toPath()); + c.report(); + int errors = c.getErrorCount(); + if (errors == 0) { + passed("No list errors found"); + } else { + failed(errors + " errors found when checking lists"); + } + } catch (IOException e) { + failed("exception thrown when reading files: " + e); + } + } + + /** + * A class to check the presence of singleton lists. + */ + public class ListChecker extends HtmlChecker { + private int listErrors; + + private boolean inBody; + private boolean inNoScript; + private Stack> counts = new Stack<>(); + private int regionErrors; + private String fileName; + private boolean inheritanceClass; + private List excludeFiles = List.of("overview-tree.html","package-tree.html","module-summary.html"); + + ListChecker(PrintStream out, Function fileReader) { + super(out, fileReader); + } + + protected int getErrorCount() { + return errors; + } + + @Override + public void report() { + if (listErrors == 0) { + out.println("All lists OK"); + } else { + out.println(listErrors + " list errors"); + } + + if (regionErrors == 0) { + out.println("All regions OK"); + } else { + out.println(regionErrors + " errors in regions"); + } + } + + @Override + public void startFile(Path path) { + fileName = path.getFileName().toString(); + } + + @Override + public void endFile() { + } + + @Override + public void docType(String doctype) { + } + + @Override + public void startElement(String name, Map attrs, boolean selfClosing) { + switch (name) { + + case "ul": case "ol": case "dl": + counts.push(new TreeMap<>()); + if (!attrs.isEmpty() && attrs.containsKey("class") + && attrs.containsValue("inheritance")) { + inheritanceClass = true; + } + break; + + case "li": case "dd": case "dt": { + Map c = counts.peek(); + c.put(name, 1 + c.computeIfAbsent(name, n -> 0)); + break; + } + } + } + + @Override + public void endElement(String name) { + switch (name) { + case "ul": case "ol": { + Map c = counts.pop(); + if (c.get("li") == 0) { + error(currFile, getLineNumber(), "empty list"); + } else if (c.get("li") == 1 && fileName != null && !excludeFiles.contains(fileName)) { + if (!inheritanceClass) { + error(currFile, getLineNumber(), "singleton list"); + } else { + inheritanceClass = false; + } + } + break; + } + + case "dl": { + Map c = counts.pop(); + if (c.get("dd") == 0 || c.get("dt") == 0) { + error(currFile, getLineNumber(), "empty list"); + } + /*if (c.get("dd") == 1 || c.get("dt") == 1) { + error(currFile, getLineNumber(), "singleton list"); + }*/ + break; + } + } + } + } + +} \ No newline at end of file diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java 2019-04-24 19:25:41.000000000 +0000 @@ -85,11 +85,14 @@ // make sure the second @summary's content is displayed correctly checkOutput("p1/A.html", true, - "
              • \n" + "
                \n" + "

                m3

                \n" + + "\n" + + "\n" + + "\n" + "
                public void m3()
                \n" + "
                First sentence some text maybe second sentence.
                \n" - + "
              • \n" + + "
          \n" ); checkOutput("p1/package-summary.html", true, diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java 2019-04-24 19:25:41.000000000 +0000 @@ -151,7 +151,7 @@ ); checkOutput("class-use/UsedInC.html", true, "
        • \n" - + "
          " + + "
          " ); checkOutput("package-use.html", true, "
      Properties 
      " diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/lib/javadoc/tester/A11yChecker.java openjdk-13-13~18/test/langtools/jdk/javadoc/lib/javadoc/tester/A11yChecker.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/lib/javadoc/tester/A11yChecker.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/lib/javadoc/tester/A11yChecker.java 2019-04-24 19:25:41.000000000 +0000 @@ -48,7 +48,7 @@ super(out, fileReader); } - int getErrorCount() { + protected int getErrorCount() { return errors; } diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlChecker.java openjdk-13-13~18/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlChecker.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlChecker.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlChecker.java 2019-04-24 19:25:41.000000000 +0000 @@ -43,15 +43,15 @@ protected int files; protected int errors; - HtmlChecker(PrintStream out, Function fileReader) { + protected HtmlChecker(PrintStream out, Function fileReader) { super(out, fileReader); } - void checkDirectory(Path dir) throws IOException { + public void checkDirectory(Path dir) throws IOException { checkFiles(List.of(dir), false, Collections.emptySet()); } - void checkFiles(List files, boolean skipSubdirs, Set excludeFiles) throws IOException { + public void checkFiles(List files, boolean skipSubdirs, Set excludeFiles) throws IOException { for (Path file : files) { Files.walkFileTree(file, new SimpleFileVisitor() { int depth = 0; @@ -86,7 +86,7 @@ } } - void checkFile(Path file) { + protected void checkFile(Path file) { try { currFile = file.toAbsolutePath().normalize(); read(file); @@ -96,9 +96,9 @@ } } - abstract void report(); + protected abstract void report(); - int getErrorCount() { + protected int getErrorCount() { return errors; } diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlParser.java openjdk-13-13~18/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlParser.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlParser.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlParser.java 2019-04-24 19:25:41.000000000 +0000 @@ -101,7 +101,7 @@ } - int getLineNumber() { + protected int getLineNumber() { return lineNumber; } diff -Nru openjdk-13-13~17/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java openjdk-13-13~18/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java --- openjdk-13-13~17/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java 2019-04-24 19:25:41.000000000 +0000 @@ -772,7 +772,7 @@ return readFile(new File(baseDir), fileName); } - private String readFile(Path file) { + protected String readFile(Path file) { File baseDir; if (file.startsWith(outputDir.toPath())) { baseDir = outputDir; diff -Nru openjdk-13-13~17/test/lib/jdk/test/lib/process/OutputAnalyzer.java openjdk-13-13~18/test/lib/jdk/test/lib/process/OutputAnalyzer.java --- openjdk-13-13~17/test/lib/jdk/test/lib/process/OutputAnalyzer.java 2019-04-17 20:18:29.000000000 +0000 +++ openjdk-13-13~18/test/lib/jdk/test/lib/process/OutputAnalyzer.java 2019-04-24 19:25:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,8 @@ import java.io.IOException; import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -57,6 +59,15 @@ } /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param file File to analyze + */ + public OutputAnalyzer(Path file) throws IOException { + this(Files.readString(file)); + } + + /** * Create an OutputAnalyzer, a utility class for verifying output * * @param stdout stdout buffer to analyze diff -Nru openjdk-13-13~17/test/micro/org/openjdk/bench/java/lang/StringEquals.java openjdk-13-13~18/test/micro/org/openjdk/bench/java/lang/StringEquals.java --- openjdk-13-13~17/test/micro/org/openjdk/bench/java/lang/StringEquals.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-13-13~18/test/micro/org/openjdk/bench/java/lang/StringEquals.java 2019-04-24 19:25:41.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.*; +import java.util.concurrent.TimeUnit; + +/* + * This benchmark naively explores String::equals performance + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class StringEquals { + + public String test = new String("0123456789"); + public String test2 = new String("tgntogjnrognagronagroangroarngorngaorng"); + public String test3 = new String(test); // equal to test, but not same + public String test4 = new String("0123\u01FF"); + public String test5 = new String(test4); // equal to test4, but not same + public String test6 = new String("0123456780"); + public String test7 = new String("0123\u01FE"); + + @Benchmark + public boolean different() { + return test.equals(test2); + } + + @Benchmark + public boolean equal() { + return test.equals(test3); + } + + @Benchmark + public boolean almostEqual() { + return test.equals(test6); + } + + @Benchmark + public boolean almostEqualUTF16() { + return test4.equals(test7); + } + + @Benchmark + public boolean differentCoders() { + return test.equals(test4); + } + + @Benchmark + public boolean equalsUTF16() { + return test5.equals(test4); + } +} +