diff --git a/.hgtags b/.hgtags index 50c1586057d..0d5f45226f5 100644 --- a/.hgtags +++ b/.hgtags @@ -334,3 +334,5 @@ f61a63b7d1e52e307abc0bfc751203155d362ec4 jdk9-b83 4a0312f2894bcbe1fd20266c8fda8d983bd2fcf6 jdk9-b89 d131f4b8433a79408f935eff9bf92a0664229b60 jdk9-b90 8077fd2f055d31e50b46fcf62d9c035bc385a215 jdk9-b91 +f242d4332f563648426a1b0fa02d8741beba19ef jdk9-b92 +09206c6513b300e1ac8541f3be012e1a49312104 jdk9-b93 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 77827b83110..14bd56395f0 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -334,3 +334,5 @@ fd4f4f7561074dc0dbc1772c8489c7b902b6b8a9 jdk9-b87 895353113f382d24e623191fdab0e29a3ce34738 jdk9-b89 cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90 122142a185381ce5cea959bf13b923d8cc333628 jdk9-b91 +106c06398f7ab330eef9e335fbd3a5a8ead23b77 jdk9-b92 +331fda57dfd323c61804ba0472776790de572937 jdk9-b93 diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 9fd553f0d86..eb053466068 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -155,6 +155,9 @@ SRCDIRS_SETUP_OUTPUT_DIRS # ############################################################################### +# See if we are doing a complete static build or not +JDKOPT_SETUP_STATIC_BUILD + # First determine the toolchain type (compiler family) TOOLCHAIN_DETERMINE_TOOLCHAIN_TYPE diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index 383f359fad3..b44c78e4300 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -221,7 +221,11 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], if test "x$OPENJDK_TARGET_OS" = xmacosx; then # Linking is different on MacOSX - SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + if test "x$STATIC_BUILD" = xtrue; then + SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup' + else + SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + fi SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/[$]1' @@ -696,7 +700,9 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \ -I${JDK_TOPDIR}/src/java.base/share/native/include \ -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include" + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \ + -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava" # The shared libraries are compiled using the picflag. CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 18e11b034c8..1b278126644 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -803,6 +803,7 @@ STATIC_LIBRARY_SUFFIX SHARED_LIBRARY_SUFFIX LIBRARY_PREFIX TOOLCHAIN_TYPE +STATIC_BUILD BUILD_HOTSPOT HOTSPOT_DIST BUILD_OUTPUT @@ -1074,6 +1075,7 @@ with_override_hotspot with_override_nashorn with_override_jdk with_import_hotspot +enable_static_build with_toolchain_type with_extra_cflags with_extra_cxxflags @@ -1852,6 +1854,7 @@ Optional Features: run the Queens test after Hotspot build [disabled] --enable-unlimited-crypto Enable unlimited crypto policy [disabled] + --enable-static-build enable static library build [disabled] --disable-warnings-as-errors do not consider native warnings to be an error [enabled] @@ -3989,6 +3992,15 @@ pkgadd_help() { # +################################################################################ +# +# Static build support. When enabled will generate static +# libraries instead of shared libraries for all JDK libs. +# + + + + # # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -29018,6 +29030,40 @@ $as_echo "yes from $HOTSPOT_DIST" >&6; } # ############################################################################### +# See if we are doing a complete static build or not + + # Check whether --enable-static-build was given. +if test "${enable_static_build+set}" = set; then : + enableval=$enable_static_build; +fi + + STATIC_BUILD=false + if test "x$enable_static_build" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if static build is enabled" >&5 +$as_echo_n "checking if static build is enabled... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + if test "x$OPENJDK_TARGET_OS" != "xmacosx"; then + as_fn_error $? "--enable-static-build is only supported for macosx builds" "$LINENO" 5 + fi + STATIC_BUILD_CFLAGS="-DSTATIC_BUILD=1" + LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $STATIC_BUILD_CFLAGS" + LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $STATIC_BUILD_CFLAGS" + CFLAGS_JDKLIB_EXTRA="$CFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS" + CXXFLAGS_JDKLIB_EXTRA="$CXXFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS" + STATIC_BUILD=true + elif test "x$enable_static_build" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if static build is enabled" >&5 +$as_echo_n "checking if static build is enabled... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + elif test "x$enable_static_build" != "x"; then + as_fn_error $? "--enable-static-build can only be assigned \"yes\" or \"no\"" "$LINENO" 5 + fi + + + + # First determine the toolchain type (compiler family) @@ -29126,8 +29172,19 @@ $as_echo "$as_me: Valid toolchains: $VALID_TOOLCHAINS." >&6;} OBJ_SUFFIX='.o' EXE_SUFFIX='' if test "x$OPENJDK_TARGET_OS" = xmacosx; then - SHARED_LIBRARY='lib$1.dylib' - SHARED_LIBRARY_SUFFIX='.dylib' + # For full static builds, we're overloading the SHARED_LIBRARY + # variables in order to limit the amount of changes required. + # It would be better to remove SHARED and just use LIBRARY and + # LIBRARY_SUFFIX for libraries that can be built either + # shared or static and use STATIC_* for libraries that are + # always built statically. + if test "x$STATIC_BUILD" = xtrue; then + SHARED_LIBRARY='lib$1.a' + SHARED_LIBRARY_SUFFIX='.a' + else + SHARED_LIBRARY='lib$1.dylib' + SHARED_LIBRARY_SUFFIX='.dylib' + fi fi fi @@ -44314,7 +44371,11 @@ $as_echo "$ac_cv_c_bigendian" >&6; } if test "x$OPENJDK_TARGET_OS" = xmacosx; then # Linking is different on MacOSX - SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + if test "x$STATIC_BUILD" = xtrue; then + SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup' + else + SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + fi SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/$1' @@ -44818,7 +44879,9 @@ $as_echo "$supports" >&6; } COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \ -I${JDK_TOPDIR}/src/java.base/share/native/include \ -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include" + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \ + -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava" # The shared libraries are compiled using the picflag. CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index ccf77879508..7c1492ed24c 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -665,3 +665,37 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE], AC_SUBST(GCOV_ENABLED) ]) + +################################################################################ +# +# Static build support. When enabled will generate static +# libraries instead of shared libraries for all JDK libs. +# +AC_DEFUN_ONCE([JDKOPT_SETUP_STATIC_BUILD], +[ + AC_ARG_ENABLE([static-build], [AS_HELP_STRING([--enable-static-build], + [enable static library build @<:@disabled@:>@])]) + STATIC_BUILD=false + if test "x$enable_static_build" = "xyes"; then + AC_MSG_CHECKING([if static build is enabled]) + AC_MSG_RESULT([yes]) + if test "x$OPENJDK_TARGET_OS" != "xmacosx"; then + AC_MSG_ERROR([--enable-static-build is only supported for macosx builds]) + fi + STATIC_BUILD_CFLAGS="-DSTATIC_BUILD=1" + LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $STATIC_BUILD_CFLAGS" + LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $STATIC_BUILD_CFLAGS" + CFLAGS_JDKLIB_EXTRA="$CFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS" + CXXFLAGS_JDKLIB_EXTRA="$CXXFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS" + STATIC_BUILD=true + elif test "x$enable_static_build" = "xno"; then + AC_MSG_CHECKING([if static build is enabled]) + AC_MSG_RESULT([no]) + elif test "x$enable_static_build" != "x"; then + AC_MSG_ERROR([--enable-static-build can only be assigned "yes" or "no"]) + fi + + AC_SUBST(STATIC_BUILD) +]) + + diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index d8212483ec9..0be7456fa2c 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -417,6 +417,7 @@ SHARED_LIBRARY_SUFFIX:=@SHARED_LIBRARY_SUFFIX@ STATIC_LIBRARY_SUFFIX:=@STATIC_LIBRARY_SUFFIX@ EXE_SUFFIX:=@EXE_SUFFIX@ OBJ_SUFFIX:=@OBJ_SUFFIX@ +STATIC_BUILD:=@STATIC_BUILD@ STRIPFLAGS:=@STRIPFLAGS@ diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 32f4881f608..18924c92be7 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -72,8 +72,19 @@ AC_DEFUN([TOOLCHAIN_SETUP_FILENAME_PATTERNS], OBJ_SUFFIX='.o' EXE_SUFFIX='' if test "x$OPENJDK_TARGET_OS" = xmacosx; then - SHARED_LIBRARY='lib[$]1.dylib' - SHARED_LIBRARY_SUFFIX='.dylib' + # For full static builds, we're overloading the SHARED_LIBRARY + # variables in order to limit the amount of changes required. + # It would be better to remove SHARED and just use LIBRARY and + # LIBRARY_SUFFIX for libraries that can be built either + # shared or static and use STATIC_* for libraries that are + # always built statically. + if test "x$STATIC_BUILD" = xtrue; then + SHARED_LIBRARY='lib[$]1.a' + SHARED_LIBRARY_SUFFIX='.a' + else + SHARED_LIBRARY='lib[$]1.dylib' + SHARED_LIBRARY_SUFFIX='.dylib' + fi fi fi diff --git a/corba/.hgtags b/corba/.hgtags index 6d0a137add8..87c538d45b5 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -334,3 +334,5 @@ a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87 c847a53b38d2fffb87afc483c74db05eced9b4f4 jdk9-b89 29cc8228d62319af21cad7c90817671e0813b6bd jdk9-b90 75843e0a9371d445a3c9b440bab85e50b5dc287c jdk9-b91 +f7d70caad89ad0c43bb057bca0aad6f17ce05a6a jdk9-b92 +27e9c8d8091e2447ea7ef3e3103e9b7dd286e03a jdk9-b93 diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java index c6eb5f7051a..3c357f61c38 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java @@ -65,7 +65,6 @@ import com.sun.corba.se.spi.presentation.rmi.StubAdapter; import com.sun.corba.se.spi.logging.CORBALogDomains; import com.sun.corba.se.impl.logging.ORBUtilSystemException; import com.sun.corba.se.impl.corba.AsynchInvoke; -import com.sun.corba.se.impl.transport.ManagedLocalsThread; public class RequestImpl extends Request @@ -256,7 +255,7 @@ public class RequestImpl public synchronized void send_deferred() { AsynchInvoke invokeObject = new AsynchInvoke(_orb, this, false); - new ManagedLocalsThread(invokeObject).start(); + new sun.misc.ManagedLocalsThread(invokeObject).start(); } public synchronized boolean poll_response() diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java index 24996d51ed0..d9dceac7ba8 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java @@ -112,7 +112,6 @@ import com.sun.corba.se.impl.util.JDKBridge; import com.sun.corba.se.impl.logging.UtilSystemException; import com.sun.corba.se.spi.logging.CORBALogDomains; import sun.corba.SharedSecrets; -import com.sun.corba.se.impl.transport.ManagedLocalsThread; /** @@ -752,7 +751,7 @@ public class Util implements javax.rmi.CORBA.UtilDelegate } } -class KeepAlive extends ManagedLocalsThread +class KeepAlive extends sun.misc.ManagedLocalsThread { boolean quit = false; diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java index d10f4e3eccd..546914d623d 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java @@ -103,7 +103,6 @@ import com.sun.corba.se.impl.orbutil.concurrent.Sync ; import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil ; import com.sun.corba.se.impl.orbutil.concurrent.ReentrantMutex ; import com.sun.corba.se.impl.orbutil.concurrent.CondVar ; -import com.sun.corba.se.impl.transport.ManagedLocalsThread; /** * POAImpl is the implementation of the Portable Object Adapter. It @@ -517,7 +516,7 @@ public class POAImpl extends ObjectAdapterBase implements POA // Converted from anonymous class to local class // so that we can call performDestroy() directly. - static class DestroyThread extends ManagedLocalsThread { + static class DestroyThread extends sun.misc.ManagedLocalsThread { private boolean wait ; private boolean etherealize ; private boolean debug ; diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java index 41100a4b3bd..22610dda9ba 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java @@ -48,7 +48,6 @@ import com.sun.corba.se.spi.protocol.PIHandler ; import com.sun.corba.se.impl.logging.POASystemException ; import com.sun.corba.se.impl.orbutil.ORBUtility ; -import com.sun.corba.se.impl.transport.ManagedLocalsThread; /** POAManagerImpl is the implementation of the POAManager interface. * Its public methods are activate(), hold_requests(), discard_requests() @@ -358,7 +357,7 @@ public class POAManagerImpl extends org.omg.CORBA.LocalObject implements if (wait_for_completion) deactivator.run() ; else { - Thread thr = new ManagedLocalsThread(deactivator) ; + Thread thr = new sun.misc.ManagedLocalsThread(deactivator) ; thr.start() ; } } finally { diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java index 21a5c340612..9e9fce8a47d 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java @@ -49,7 +49,6 @@ import com.sun.corba.se.impl.javax.rmi.CORBA.Util ; import com.sun.corba.se.spi.oa.OAInvocationInfo ; import com.sun.corba.se.spi.oa.NullServant ; -import com.sun.corba.se.impl.transport.ManagedLocalsThread; /** Implementation of POARequesHandler that provides policy specific * operations on the POA. @@ -303,7 +302,7 @@ public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R { throw new WrongPolicy(); } - class Etherealizer extends ManagedLocalsThread { + class Etherealizer extends sun.misc.ManagedLocalsThread { private POAPolicyMediatorImpl_R_USM mediator ; private ActiveObjectMap.Key key ; private AOMEntry entry ; diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java index bb67c3cd654..82da35a7921 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java @@ -165,7 +165,6 @@ import com.sun.corba.se.impl.util.Utility; import com.sun.corba.se.impl.logging.ORBUtilSystemException; import com.sun.corba.se.impl.copyobject.CopierManagerImpl; import com.sun.corba.se.impl.presentation.rmi.PresentationManagerImpl; -import com.sun.corba.se.impl.transport.ManagedLocalsThread; /** * The JavaIDL ORB implementation. @@ -692,7 +691,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB for (int i = 0; i < req.length; i++) { AsynchInvoke invokeObject = new AsynchInvoke( this, (com.sun.corba.se.impl.corba.RequestImpl)req[i], true); - new ManagedLocalsThread(invokeObject).start(); + new sun.misc.ManagedLocalsThread(invokeObject).start(); } } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java index 12a8127d061..9a0e56afc4f 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java @@ -54,7 +54,6 @@ import com.sun.corba.se.spi.monitoring.LongMonitoredAttributeBase; import com.sun.corba.se.impl.logging.ORBUtilSystemException; import com.sun.corba.se.impl.orbutil.ORBConstants; import com.sun.corba.se.spi.logging.CORBALogDomains; -import com.sun.corba.se.impl.transport.ManagedLocalsThread; public class ThreadPoolImpl implements ThreadPool { @@ -460,7 +459,7 @@ public class ThreadPoolImpl implements ThreadPool } - private class WorkerThread extends ManagedLocalsThread implements Closeable + private class WorkerThread extends sun.misc.ManagedLocalsThread implements Closeable { private Work currentWork; private int threadId = 0; // unique id for the thread diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/ManagedLocalsThread.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/ManagedLocalsThread.java deleted file mode 100644 index b888de30228..00000000000 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/ManagedLocalsThread.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2015, 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 com.sun.corba.se.impl.transport; - -import sun.misc.Unsafe; -import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * A thread that has it's thread locals, and inheritable thread - * locals erased on construction. - */ -public class ManagedLocalsThread extends Thread { - private static final Unsafe UNSAFE; - private static final long THREAD_LOCALS; - private static final long INHERITABLE_THREAD_LOCALS; - - public ManagedLocalsThread () { - super(); - } - - public ManagedLocalsThread(String name) { - super(name); - eraseThreadLocals(); - } - public ManagedLocalsThread(Runnable target) { - super(target); - eraseThreadLocals(); - } - - public ManagedLocalsThread(Runnable target, String name) { - super(target, name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) { - super(group, target, name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, String name) { - super(group, name); - eraseThreadLocals(); - } - - /** - * Drops all thread locals (and inherited thread locals). - */ - public final void eraseThreadLocals() { - UNSAFE.putObject(this, THREAD_LOCALS, null); - UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null); - } - - private static Unsafe getUnsafe() { - PrivilegedAction pa = () -> { - Class unsafeClass = sun.misc.Unsafe.class; - try { - Field f = unsafeClass.getDeclaredField("theUnsafe"); - f.setAccessible(true); - return (Unsafe) f.get(null); - } catch (Exception e) { - throw new Error(e); - } - }; - return AccessController.doPrivileged(pa); - } - - private static long getThreadFieldOffset(String fieldName) { - PrivilegedAction pa = () -> { - Class t = Thread.class; - long fieldOffset; - try { - fieldOffset = UNSAFE.objectFieldOffset(t - .getDeclaredField("inheritableThreadLocals")); - } catch (Exception e) { - throw new Error(e); - } - return fieldOffset; - }; - return AccessController.doPrivileged(pa); - } - - static { - UNSAFE = getUnsafe(); - try { - THREAD_LOCALS = getThreadFieldOffset("threadLocals"); - INHERITABLE_THREAD_LOCALS = getThreadFieldOffset("inheritableThreadLocals"); - } catch (Exception e) { - throw new Error(e); - } - } -} diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java index 4acac0a176e..c43c1dfa7b5 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java @@ -57,7 +57,7 @@ import com.sun.corba.se.impl.orbutil.ORBUtility; */ class SelectorImpl extends - ManagedLocalsThread + sun.misc.ManagedLocalsThread implements com.sun.corba.se.pept.transport.Selector { diff --git a/corba/src/java.corba/share/classes/sun/corba/Bridge.java b/corba/src/java.corba/share/classes/sun/corba/Bridge.java index 987ee097376..1891612219c 100644 --- a/corba/src/java.corba/share/classes/sun/corba/Bridge.java +++ b/corba/src/java.corba/share/classes/sun/corba/Bridge.java @@ -36,7 +36,7 @@ import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; -import sun.misc.Unsafe ; +import jdk.internal.misc.Unsafe ; import sun.reflect.ReflectionFactory ; /** This class provides the methods for fundamental JVM operations @@ -120,7 +120,7 @@ public final class Bridge Field fld = null ; try { - Class unsafeClass = sun.misc.Unsafe.class ; + Class unsafeClass = jdk.internal.misc.Unsafe.class ; fld = unsafeClass.getDeclaredField( "theUnsafe" ) ; fld.setAccessible( true ) ; return fld ; diff --git a/corba/src/java.corba/share/classes/sun/corba/SharedSecrets.java b/corba/src/java.corba/share/classes/sun/corba/SharedSecrets.java index b4c56080f9f..19ff5bddcfa 100644 --- a/corba/src/java.corba/share/classes/sun/corba/SharedSecrets.java +++ b/corba/src/java.corba/share/classes/sun/corba/SharedSecrets.java @@ -26,7 +26,7 @@ package sun.corba; import com.sun.corba.se.impl.io.ValueUtility; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import java.lang.reflect.Field; import java.security.AccessController; @@ -48,7 +48,7 @@ public class SharedSecrets { private static Unsafe getUnsafe() { PrivilegedAction pa = () -> { - Class unsafeClass = sun.misc.Unsafe.class ; + Class unsafeClass = jdk.internal.misc.Unsafe.class ; try { Field f = unsafeClass.getDeclaredField("theUnsafe"); f.setAccessible(true); diff --git a/hotspot/.hgignore b/hotspot/.hgignore index d9bdc622912..8bd4af0eb82 100644 --- a/hotspot/.hgignore +++ b/hotspot/.hgignore @@ -11,3 +11,12 @@ ^.hgtip .DS_Store \.class$ +^\.?mx.jvmci/ +^src/jdk.vm.ci/share/classes/\w[\w\.]*/.*\.xml +^src/jdk.vm.ci/share/classes/\w[\w\.]*/.*\.iml +^src/jdk.vm.ci/share/classes/\w[\w\.]*/nbproject +^src/jdk.vm.ci/share/classes/\w[\w\.]*/\..* +^test/compiler/jvmci/\w[\w\.]*/.*\.xml +^test/compiler/jvmci/\w[\w\.]*/.*\.iml +^test/compiler/jvmci/\w[\w\.]*/nbproject +^test/compiler/jvmci/\w[\w\.]*/\..* diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 430d279731b..a1e494812fe 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -494,3 +494,5 @@ bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88 20dff0211deda8d5877fda0e80b6d165ab93c6c2 jdk9-b89 7fe46dc64bb3a8df554b24cde0153ffb24f39c5e jdk9-b90 3fd5c2ca4c20c183628b6dbeb8df821a961419e3 jdk9-b91 +53cb98d68a1aeb08d29c89d6da748de60c448e37 jdk9-b92 +d8b24776484cc4dfd19f50b23eaa18a80a161371 jdk9-b93 diff --git a/hotspot/agent/src/os/linux/libproc_impl.c b/hotspot/agent/src/os/linux/libproc_impl.c index 97d3acf9282..84154be4eb0 100644 --- a/hotspot/agent/src/os/linux/libproc_impl.c +++ b/hotspot/agent/src/os/linux/libproc_impl.c @@ -38,6 +38,7 @@ int pathmap_open(const char* name) { int fd; char alt_path[PATH_MAX + 1], *alt_path_end; const char *s; + int free_space; if (!alt_root_initialized) { alt_root_initialized = -1; @@ -48,14 +49,22 @@ int pathmap_open(const char* name) { return open(name, O_RDONLY); } - strcpy(alt_path, alt_root); - alt_path_end = alt_path + strlen(alt_path); - // Strip path items one by one and try to open file with alt_root prepended + if (strlen(alt_root) + strlen(name) < PATH_MAX) { + // Buffer too small. + return -1; + } + + strncpy(alt_path, alt_root, PATH_MAX); + alt_path[PATH_MAX] = '\0'; + alt_path_end = alt_path + strlen(alt_path); + free_space = PATH_MAX + 1 - (alt_path_end-alt_path); + + // Strip path items one by one and try to open file with alt_root prepended. s = name; while (1) { - strcat(alt_path, s); - s += 1; + strncat(alt_path, s, free_space); + s += 1; // Skip /. fd = open(alt_path, O_RDONLY); if (fd >= 0) { @@ -70,7 +79,8 @@ int pathmap_open(const char* name) { break; } - *alt_path_end = 0; + // Cut off what we appended above. + *alt_path_end = '\0'; } return -1; diff --git a/hotspot/agent/src/os/linux/ps_core.c b/hotspot/agent/src/os/linux/ps_core.c index 268fc2ad162..6c39d0c43f5 100644 --- a/hotspot/agent/src/os/linux/ps_core.c +++ b/hotspot/agent/src/os/linux/ps_core.c @@ -774,72 +774,78 @@ err: // process segments from interpreter (ld.so or ld-linux.so) static bool read_interp_segments(struct ps_prochandle* ph) { - ELF_EHDR interp_ehdr; + ELF_EHDR interp_ehdr; - if (read_elf_header(ph->core->interp_fd, &interp_ehdr) != true) { - print_debug("interpreter is not a valid ELF file\n"); - return false; - } + if (read_elf_header(ph->core->interp_fd, &interp_ehdr) != true) { + print_debug("interpreter is not a valid ELF file\n"); + return false; + } - if (read_lib_segments(ph, ph->core->interp_fd, &interp_ehdr, ph->core->ld_base_addr) != true) { - print_debug("can't read segments of interpreter\n"); - return false; - } + if (read_lib_segments(ph, ph->core->interp_fd, &interp_ehdr, ph->core->ld_base_addr) != true) { + print_debug("can't read segments of interpreter\n"); + return false; + } - return true; + return true; } // process segments of a a.out static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) { - int i = 0; - ELF_PHDR* phbuf = NULL; - ELF_PHDR* exec_php = NULL; + int i = 0; + ELF_PHDR* phbuf = NULL; + ELF_PHDR* exec_php = NULL; - if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL) - return false; + if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL) { + return false; + } - for (exec_php = phbuf, i = 0; i < exec_ehdr->e_phnum; i++) { - switch (exec_php->p_type) { + for (exec_php = phbuf, i = 0; i < exec_ehdr->e_phnum; i++) { + switch (exec_php->p_type) { - // add mappings for PT_LOAD segments - case PT_LOAD: { - // add only non-writable segments of non-zero filesz - if (!(exec_php->p_flags & PF_W) && exec_php->p_filesz != 0) { - if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz) == NULL) goto err; - } - break; - } + // add mappings for PT_LOAD segments + case PT_LOAD: { + // add only non-writable segments of non-zero filesz + if (!(exec_php->p_flags & PF_W) && exec_php->p_filesz != 0) { + if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz) == NULL) goto err; + } + break; + } - // read the interpreter and it's segments - case PT_INTERP: { - char interp_name[BUF_SIZE]; + // read the interpreter and it's segments + case PT_INTERP: { + char interp_name[BUF_SIZE + 1]; - pread(ph->core->exec_fd, interp_name, MIN(exec_php->p_filesz, BUF_SIZE), exec_php->p_offset); - print_debug("ELF interpreter %s\n", interp_name); - // read interpreter segments as well - if ((ph->core->interp_fd = pathmap_open(interp_name)) < 0) { - print_debug("can't open runtime loader\n"); - goto err; - } - break; - } + // BUF_SIZE is PATH_MAX + NAME_MAX + 1. + if (exec_php->p_filesz > BUF_SIZE) { + goto err; + } + pread(ph->core->exec_fd, interp_name, exec_php->p_filesz, exec_php->p_offset); + interp_name[exec_php->p_filesz] = '\0'; + print_debug("ELF interpreter %s\n", interp_name); + // read interpreter segments as well + if ((ph->core->interp_fd = pathmap_open(interp_name)) < 0) { + print_debug("can't open runtime loader\n"); + goto err; + } + break; + } - // from PT_DYNAMIC we want to read address of first link_map addr - case PT_DYNAMIC: { - ph->core->dynamic_addr = exec_php->p_vaddr; - print_debug("address of _DYNAMIC is 0x%lx\n", ph->core->dynamic_addr); - break; - } + // from PT_DYNAMIC we want to read address of first link_map addr + case PT_DYNAMIC: { + ph->core->dynamic_addr = exec_php->p_vaddr; + print_debug("address of _DYNAMIC is 0x%lx\n", ph->core->dynamic_addr); + break; + } - } // switch - exec_php++; - } // for + } // switch + exec_php++; + } // for - free(phbuf); - return true; -err: - free(phbuf); - return false; + free(phbuf); + return true; + err: + free(phbuf); + return false; } diff --git a/hotspot/agent/src/os/linux/symtab.c b/hotspot/agent/src/os/linux/symtab.c index 61c98747854..1c96cf3e370 100644 --- a/hotspot/agent/src/os/linux/symtab.c +++ b/hotspot/agent/src/os/linux/symtab.c @@ -545,6 +545,7 @@ uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, return (uintptr_t)NULL; item.key = (char*) strdup(sym_name); + item.data = NULL; hsearch_r(item, FIND, &ret, symtab->hash_table); if (ret) { struct elf_symbol * sym = (struct elf_symbol *)(ret->data); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java index ef8a7e1849e..3afdab8a761 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java @@ -40,8 +40,7 @@ public class OopUtilities implements /* imports */ JVMTIThreadState { // FIXME: access should be synchronized and cleared when VM is // resumed // String fields - private static IntField offsetField; - private static IntField countField; + private static ByteField coderField; private static OopField valueField; // ThreadGroup fields private static OopField threadGroupParentField; @@ -96,20 +95,30 @@ public class OopUtilities implements /* imports */ JVMTIThreadState { if (charArray == null) { return null; } - return charArrayToString(charArray, 0, (int) charArray.getLength()); + int length = (int)charArray.getLength(); + StringBuffer buf = new StringBuffer(length); + for (int i = 0; i < length; i++) { + buf.append(charArray.getCharAt(i)); + } + return buf.toString(); } - public static String charArrayToString(TypeArray charArray, int offset, int length) { - if (charArray == null) { + public static String byteArrayToString(TypeArray byteArray, byte coder) { + if (byteArray == null) { return null; } - final int limit = offset + length; - if (Assert.ASSERTS_ENABLED) { - Assert.that(offset >= 0 && limit <= charArray.getLength(), "out of bounds"); - } + int length = (int)byteArray.getLength() >> coder; StringBuffer buf = new StringBuffer(length); - for (int i = offset; i < limit; i++) { - buf.append(charArray.getCharAt(i)); + if (coder == 0) { + // Latin1 encoded + for (int i = 0; i < length; i++) { + buf.append((char)(byteArray.getByteAt(i) & 0xff)); + } + } else { + // UTF16 encoded + for (int i = 0; i < length; i++) { + buf.append(byteArray.getCharAt(i)); + } } return buf.toString(); } @@ -141,21 +150,14 @@ public class OopUtilities implements /* imports */ JVMTIThreadState { } public static String stringOopToString(Oop stringOop) { - if (offsetField == null) { - InstanceKlass k = (InstanceKlass) stringOop.getKlass(); - offsetField = (IntField) k.findField("offset", "I"); // optional - countField = (IntField) k.findField("count", "I"); // optional - valueField = (OopField) k.findField("value", "[C"); - if (Assert.ASSERTS_ENABLED) { - Assert.that(valueField != null, "Field \'value\' of java.lang.String not found"); - } + InstanceKlass k = (InstanceKlass) stringOop.getKlass(); + coderField = (ByteField) k.findField("coder", "B"); + valueField = (OopField) k.findField("value", "[B"); + if (Assert.ASSERTS_ENABLED) { + Assert.that(coderField != null, "Field \'coder\' of java.lang.String not found"); + Assert.that(valueField != null, "Field \'value\' of java.lang.String not found"); } - if (offsetField != null && countField != null) { - return charArrayToString((TypeArray) valueField.getValue(stringOop), - offsetField.getValue(stringOop), - countField.getValue(stringOop)); - } - return charArrayToString((TypeArray) valueField.getValue(stringOop)); + return byteArrayToString((TypeArray) valueField.getValue(stringOop), coderField.getValue(stringOop)); } public static String stringOopToEscapedString(Oop stringOop) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java index f10e0b4c418..893c5e1e31b 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java @@ -268,8 +268,8 @@ public class HeapSummary extends Tool { VM vm = VM.getVM(); SystemDictionary sysDict = vm.getSystemDictionary(); InstanceKlass strKlass = sysDict.getStringKlass(); - // String has a field named 'value' of type 'char[]'. - stringValueField = (OopField) strKlass.findField("value", "[C"); + // String has a field named 'value' of type 'byte[]'. + stringValueField = (OopField) strKlass.findField("value", "[B"); } private long stringSize(Instance instance) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java index e2281e7b321..ea4fa581a8e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java @@ -61,9 +61,8 @@ public class Hashtable extends BasicHashtable { long h = 0; int s = 0; int len = buf.length; - // Emulate the unsigned int in java_lang_String::hash_code while (len-- > 0) { - h = 31*h + (0xFFFFFFFFL & buf[s]); + h = 31*h + (0xFFL & buf[s]); s++; } return h & 0xFFFFFFFFL; diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index 6475b29b255..cf1a4167e18 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2015, 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 @@ -403,6 +403,8 @@ $(EXPORT_LIB_ARCH_DIR)/%.dSYM: $(C2_BUILD_DIR)/%.dSYM $(install-dir) $(EXPORT_SERVER_DIR)/%.dSYM: $(C2_BUILD_DIR)/%.dSYM $(install-dir) +$(EXPORT_SERVER_DIR)/%.symbols: $(C2_BUILD_DIR)/%.symbols + $(install-file) endif # Client (C1) diff --git a/hotspot/make/aix/makefiles/mapfile-vers-debug b/hotspot/make/aix/makefiles/mapfile-vers-debug index 048af4535d5..fb75f3dfcea 100644 --- a/hotspot/make/aix/makefiles/mapfile-vers-debug +++ b/hotspot/make/aix/makefiles/mapfile-vers-debug @@ -39,7 +39,6 @@ SUNWprivate_1.1 { jio_snprintf; jio_vfprintf; jio_vsnprintf; - fork1; numa_warn; numa_error; diff --git a/hotspot/make/aix/makefiles/mapfile-vers-product b/hotspot/make/aix/makefiles/mapfile-vers-product index 1fa9c284d8b..ec0f06d8f65 100644 --- a/hotspot/make/aix/makefiles/mapfile-vers-product +++ b/hotspot/make/aix/makefiles/mapfile-vers-product @@ -34,7 +34,6 @@ SUNWprivate_1.1 { jio_snprintf; jio_vfprintf; jio_vsnprintf; - fork1; numa_warn; numa_error; diff --git a/hotspot/make/aix/makefiles/trace.make b/hotspot/make/aix/makefiles/trace.make index 11a92c8ff46..c00b0e3383a 100644 --- a/hotspot/make/aix/makefiles/trace.make +++ b/hotspot/make/aix/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2015, 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 @@ -82,8 +82,7 @@ all: $(TraceGeneratedFiles) GENERATE_CODE= \ $(QUIETLY) echo $(LOG_INFO) Generating $@; \ - $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@; \ - test -f $@ + $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@ $(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/bsd/makefiles/buildtree.make b/hotspot/make/bsd/makefiles/buildtree.make index b1f9e02f3c3..e48d6aba104 100644 --- a/hotspot/make/bsd/makefiles/buildtree.make +++ b/hotspot/make/bsd/makefiles/buildtree.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2015, 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 @@ -224,6 +224,11 @@ flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst echo "OPENJDK = $(OPENJDK)"; \ echo "$(LP64_SETTING/$(DATA_MODE))"; \ echo; \ + echo "STATIC_BUILD = $(STATIC_BUILD)"; \ + echo "COMPILER_WARNINGS_FATAL = $(COMPILER_WARNINGS_FATAL)"; \ + echo "EXTRA_LDFLAGS = $(EXTRA_LDFLAGS)"; \ + echo "LIBRARY_SUFFIX = $(LIBRARY_SUFFIX)"; \ + echo; \ echo "# Used for platform dispatching"; \ echo "TARGET_DEFINES = -DTARGET_OS_FAMILY_\$$(Platform_os_family)"; \ echo "TARGET_DEFINES += -DTARGET_ARCH_\$$(Platform_arch)"; \ diff --git a/hotspot/make/bsd/makefiles/defs.make b/hotspot/make/bsd/makefiles/defs.make index 74f2fedd8b7..a418eeb8e1d 100644 --- a/hotspot/make/bsd/makefiles/defs.make +++ b/hotspot/make/bsd/makefiles/defs.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2015, 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 @@ -186,13 +186,16 @@ ifeq ($(JDK6_OR_EARLIER),0) # executed multiple times. We reduce the noise by at least checking that # BUILD_FLAVOR has been set. ifneq ($(BUILD_FLAVOR),) - ifeq ($(BUILD_FLAVOR), product) - FULL_DEBUG_SYMBOLS ?= 1 - ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS) - else - # debug variants always get Full Debug Symbols (if available) - ENABLE_FULL_DEBUG_SYMBOLS = 1 - endif + # FULL_DEBUG_SYMBOLS not created for individual static libraries + ifeq ($(STATIC_BUILD),false) + ifeq ($(BUILD_FLAVOR), product) + FULL_DEBUG_SYMBOLS ?= 1 + ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS) + else + # debug variants always get Full Debug Symbols (if available) + ENABLE_FULL_DEBUG_SYMBOLS = 1 + endif + endif $(eval $(call print_info, "ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")) # since objcopy is optional, we set ZIP_DEBUGINFO_FILES later @@ -256,16 +259,24 @@ endif # JDK_6_OR_EARLIER JDK_INCLUDE_SUBDIR=bsd # Library suffix -ifeq ($(OS_VENDOR),Darwin) - LIBRARY_SUFFIX=dylib +ifneq ($(STATIC_BUILD),true) + ifeq ($(OS_VENDOR),Darwin) + LIBRARY_SUFFIX=dylib + else + LIBRARY_SUFFIX=so + endif else - LIBRARY_SUFFIX=so + LIBRARY_SUFFIX=a endif + EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html +# jsig library not needed for static builds +ifneq ($(STATIC_BUILD),true) # client and server subdirectories have symbolic links to ../libjsig.so -EXPORT_LIST += $(EXPORT_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX) + EXPORT_LIST += $(EXPORT_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX) +endif ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) ifeq ($(ZIP_DEBUGINFO_FILES),1) @@ -286,6 +297,9 @@ EXPORT_MINIMAL_DIR = $(EXPORT_LIB_ARCH_DIR)/minimal ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX) + ifeq ($(STATIC_BUILD),true) + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.symbols + endif ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) ifeq ($(ZIP_DEBUGINFO_FILES),1) @@ -303,6 +317,9 @@ endif ifeq ($(JVM_VARIANT_CLIENT),true) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX) + ifeq ($(STATIC_BUILD),true) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.symbols + endif ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) ifeq ($(ZIP_DEBUGINFO_FILES),1) @@ -320,6 +337,9 @@ endif ifeq ($(JVM_VARIANT_MINIMAL1),true) EXPORT_LIST += $(EXPORT_MINIMAL_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_MINIMAL_DIR)/libjvm.$(LIBRARY_SUFFIX) + ifeq ($(STATIC_BUILD),true) + EXPORT_LIST += $(EXPORT_MINIMAL_DIR)/libjvm.symbols + endif endif # Serviceability Binaries @@ -388,7 +408,9 @@ ifeq ($(OS_VENDOR), Darwin) endif # Binaries to 'universalize' if built - UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/libjsig.$(LIBRARY_SUFFIX) + ifneq ($(STATIC_BUILD),true) + UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/libjsig.$(LIBRARY_SUFFIX) + endif UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/libsaproc.$(LIBRARY_SUFFIX) UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/server/libjvm.$(LIBRARY_SUFFIX) UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/client/libjvm.$(LIBRARY_SUFFIX) @@ -396,6 +418,13 @@ ifeq ($(OS_VENDOR), Darwin) # Files to simply copy in place UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/server/Xusage.txt UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/client/Xusage.txt + + ifeq ($(STATIC_BUILD),true) + UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/server/libjvm.symbols + UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/client/libjvm.symbols + UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/minimal/libjvm.symbols + endif + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) ifeq ($(ZIP_DEBUGINFO_FILES),1) UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/server/libjvm.diz diff --git a/hotspot/make/bsd/makefiles/dtrace.make b/hotspot/make/bsd/makefiles/dtrace.make index c506679b1f8..e2af31ea7a0 100644 --- a/hotspot/make/bsd/makefiles/dtrace.make +++ b/hotspot/make/bsd/makefiles/dtrace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2015, 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,15 +37,15 @@ DtraceOutDir = $(GENERATED)/dtracefiles # Bsd does not build libjvm_db, does not compile on macosx # disabled in build: rule in vm.make JVM_DB = libjvm_db -LIBJVM_DB = libjvm_db.dylib +LIBJVM_DB = libjvm_db.$(LIBRARY_SUFFIX) -LIBJVM_DB_DEBUGINFO = libjvm_db.dylib.dSYM +LIBJVM_DB_DEBUGINFO = libjvm_db.$(LIBRARY_SUFFIX).dSYM LIBJVM_DB_DIZ = libjvm_db.diz JVM_DTRACE = jvm_dtrace -LIBJVM_DTRACE = libjvm_dtrace.dylib +LIBJVM_DTRACE = libjvm_dtrace.$(LIBRARY_SUFFIX) -LIBJVM_DTRACE_DEBUGINFO = libjvm_dtrace.dylib.dSYM +LIBJVM_DTRACE_DEBUGINFO = libjvm_dtrace.$(LIBRARY_SUFFIX).dSYM LIBJVM_DTRACE_DIZ = libjvm_dtrace.diz JVMOFFS = JvmOffsets @@ -167,14 +167,14 @@ endif # ifneq ("${ISA}","${BUILDARCH}") LFLAGS_GENOFFS += -L. -lib$(GENOFFS).dylib: $(DTRACE_SRCDIR)/$(GENOFFS).cpp $(DTRACE_SRCDIR)/$(GENOFFS).h \ +lib$(GENOFFS).$(LIBRARY_SUFFIX): $(DTRACE_SRCDIR)/$(GENOFFS).cpp $(DTRACE_SRCDIR)/$(GENOFFS).h \ $(LIBJVM.o) $(QUIETLY) $(CXX) $(CXXFLAGS) $(GENOFFS_CFLAGS) $(SHARED_FLAG) $(PICFLAG) \ $(LFLAGS_GENOFFS) -o $@ $(DTRACE_SRCDIR)/$(GENOFFS).cpp -ljvm -$(GENOFFS): $(DTRACE_SRCDIR)/$(GENOFFS)Main.c lib$(GENOFFS).dylib +$(GENOFFS): $(DTRACE_SRCDIR)/$(GENOFFS)Main.c lib$(GENOFFS).$(LIBRARY_SUFFIX) $(QUIETLY) $(LINK.CXX) -o $@ $(DTRACE_SRCDIR)/$(GENOFFS)Main.c \ - ./lib$(GENOFFS).dylib + ./lib$(GENOFFS).$(LIBRARY_SUFFIX) # $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs. $(JVMOFFS).h: $(GENOFFS) diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index 60187bdc27f..fc7b25fceaa 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2015, 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 @@ -187,7 +187,14 @@ ifeq ($(JVM_VARIANT_ZEROSHARK), true) CFLAGS += $(LIBFFI_CFLAGS) CFLAGS += $(LLVM_CFLAGS) endif + +ifeq ($(STATIC_BUILD),true) +CXXFLAGS += -DSTATIC_BUILD +CFLAGS += -DSTATIC_BUILD +else CFLAGS += $(VM_PICFLAG) +endif + CFLAGS += -fno-rtti CFLAGS += -fno-exceptions ifeq ($(USE_CLANG),) diff --git a/hotspot/make/bsd/makefiles/jsig.make b/hotspot/make/bsd/makefiles/jsig.make index 6a9cebbb337..585a0f45ba9 100644 --- a/hotspot/make/bsd/makefiles/jsig.make +++ b/hotspot/make/bsd/makefiles/jsig.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -28,9 +28,9 @@ JSIG = jsig ifeq ($(OS_VENDOR), Darwin) - LIBJSIG = lib$(JSIG).dylib + LIBJSIG = lib$(JSIG).$(LIBRARY_SUFFIX) - LIBJSIG_DEBUGINFO = lib$(JSIG).dylib.dSYM + LIBJSIG_DEBUGINFO = lib$(JSIG).$(LIBRARY_SUFFIX).dSYM LIBJSIG_DIZ = lib$(JSIG).diz else LIBJSIG = lib$(JSIG).so @@ -61,8 +61,14 @@ endif $(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE) @echo $(LOG_INFO) Making signal interposition lib... +ifeq ($(STATIC_BUILD),true) + $(QUIETLY) $(CC) -c $(SYMFLAG) $(EXTRA_CFLAGS) $(ARCHFLAG) $(PICFLAG) \ + $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $(JSIG).o $< + $(QUIETLY) $(AR) $(ARFLAGS) $@ $(JSIG).o +else $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ - $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $< + $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $< +endif ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) ifeq ($(OS_VENDOR), Darwin) $(DSYMUTIL) $@ diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug index 1fa9c284d8b..ec0f06d8f65 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug @@ -34,7 +34,6 @@ SUNWprivate_1.1 { jio_snprintf; jio_vfprintf; jio_vsnprintf; - fork1; numa_warn; numa_error; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product index 1fa9c284d8b..ec0f06d8f65 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-product @@ -34,7 +34,6 @@ SUNWprivate_1.1 { jio_snprintf; jio_vfprintf; jio_vsnprintf; - fork1; numa_warn; numa_error; diff --git a/hotspot/make/bsd/makefiles/rules.make b/hotspot/make/bsd/makefiles/rules.make index 2c4c38658c6..d2334a70ffb 100644 --- a/hotspot/make/bsd/makefiles/rules.make +++ b/hotspot/make/bsd/makefiles/rules.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2015, 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 @@ -39,7 +39,11 @@ AS.S = $(AS) $(ASFLAGS) COMPILE.CC = $(CC_COMPILE) -c GENASM.CC = $(CC_COMPILE) -S LINK.CC = $(CC) $(LFLAGS) $(AOUT_FLAGS) $(PROF_AOUT_FLAGS) +ifeq ($(STATIC_BUILD),true) +LINK_LIB.CC = $(AR) $(ARFLAGS) +else LINK_LIB.CC = $(CC) $(LFLAGS) $(SHARED_FLAG) +endif PREPROCESS.CC = $(CC_COMPILE) -E COMPILE.CXX = $(CXX_COMPILE) -c diff --git a/hotspot/make/bsd/makefiles/saproc.make b/hotspot/make/bsd/makefiles/saproc.make index 8c7545a5ee7..c1783c470a7 100644 --- a/hotspot/make/bsd/makefiles/saproc.make +++ b/hotspot/make/bsd/makefiles/saproc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -28,9 +28,9 @@ SAPROC = saproc ifeq ($(OS_VENDOR), Darwin) - LIBSAPROC = lib$(SAPROC).dylib + LIBSAPROC = lib$(SAPROC).$(LIBRARY_SUFFIX) - LIBSAPROC_DEBUGINFO = lib$(SAPROC).dylib.dSYM + LIBSAPROC_DEBUGINFO = lib$(SAPROC).$(LIBRARY_SUFFIX).dSYM LIBSAPROC_DIZ = lib$(SAPROC).diz else LIBSAPROC = lib$(SAPROC).so diff --git a/hotspot/make/bsd/makefiles/trace.make b/hotspot/make/bsd/makefiles/trace.make index ed2eb159aee..c7ef3d8ea01 100644 --- a/hotspot/make/bsd/makefiles/trace.make +++ b/hotspot/make/bsd/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2015, 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,8 +83,7 @@ all: $(TraceGeneratedFiles) GENERATE_CODE= \ $(QUIETLY) echo $(LOG_INFO) Generating $@; \ - $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@; \ - test -f $@ + $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@ $(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/bsd/makefiles/vm.make b/hotspot/make/bsd/makefiles/vm.make index 562d1f45729..71012e96193 100644 --- a/hotspot/make/bsd/makefiles/vm.make +++ b/hotspot/make/bsd/makefiles/vm.make @@ -142,10 +142,10 @@ include $(MAKEFILES_DIR)/dtrace.make JVM = jvm ifeq ($(OS_VENDOR), Darwin) - LIBJVM = lib$(JVM).dylib + LIBJVM = lib$(JVM).$(LIBRARY_SUFFIX) CFLAGS += -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE - LIBJVM_DEBUGINFO = lib$(JVM).dylib.dSYM + LIBJVM_DEBUGINFO = lib$(JVM).$(LIBRARY_SUFFIX).dSYM LIBJVM_DIZ = lib$(JVM).diz else LIBJVM = lib$(JVM).so @@ -261,6 +261,16 @@ mapfile : $(MAPFILE) mapfile_extra vm.def { print $$0 } \ }' > $@ < $(MAPFILE) +ifeq ($(STATIC_BUILD),true) +EXPORTED_SYMBOLS = libjvm.symbols + +libjvm.symbols : mapfile + $(CP) mapfile libjvm.symbols + +else +EXPORTED_SYMBOLS = +endif + mapfile_reorder : mapfile $(REORDERFILE) rm -f $@ cat $^ > $@ @@ -288,9 +298,11 @@ else LFLAGS_VM += $(SONAMEFLAG:SONAME=$(LIBJVM)) ifeq ($(OS_VENDOR), Darwin) - LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/. - LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/.. - LFLAGS_VM += -Xlinker -install_name -Xlinker @rpath/$(@F) + ifneq ($(STATIC_BUILD),true) + LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/. + LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/.. + LFLAGS_VM += -Xlinker -install_name -Xlinker @rpath/$(@F) + endif else LFLAGS_VM += -Wl,-z,defs endif @@ -345,6 +357,10 @@ LD_SCRIPT_FLAG = -Wl,-T,$(LD_SCRIPT) endif $(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT) +ifeq ($(STATIC_BUILD),true) + echo Linking static vm...; + $(LINK_LIB.CC) $@ $(LIBJVM.o) +else $(QUIETLY) { \ echo $(LOG_INFO) Linking vm...; \ $(LINK_LIB.CXX/PRE_HOOK) \ @@ -354,6 +370,8 @@ $(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT) rm -f $@.1; ln -s $@ $@.1; \ } +endif + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) ifeq ($(OS_VENDOR), Darwin) $(DSYMUTIL) $@ @@ -410,10 +428,10 @@ include $(MAKEFILES_DIR)/saproc.make ifeq ($(OS_VENDOR), Darwin) # no libjvm_db for macosx -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(EXPORTED_SYMBOLS) echo "Doing vm.make build:" else -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) $(EXPORTED_SYMBOLS) endif install: install_jvm install_jsig install_saproc diff --git a/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk index 123d3882d42..654a7f8fd32 100644 --- a/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk +++ b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk @@ -56,10 +56,10 @@ $(eval $(call SetupJavaCompilation, BUILD_JVMCI_SERVICE, \ ################################################################################ PROC_SRC_SUBDIRS := \ - jdk.vm.ci.compiler \ jdk.vm.ci.hotspot \ jdk.vm.ci.hotspot.amd64 \ jdk.vm.ci.hotspot.sparc \ + jdk.vm.ci.runtime \ # PROC_SRC_DIRS := $(patsubst %, $(SRC_DIR)/%/src, $(PROC_SRC_SUBDIRS)) @@ -94,11 +94,7 @@ TARGETS += $(GENSRC_DIR)/_gensrc_proc_done $(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors: \ $(GENSRC_DIR)/_gensrc_proc_done $(MKDIR) -p $(@D) - ($(CD) $(GENSRC_DIR)/META-INF/jvmci.options && \ - $(RM) -f $@; \ - for i in $$(ls); do \ - echo $${i}_OptionDescriptors >> $@; \ - done) + $(FIND) $(GENSRC_DIR) -name '*_OptionDescriptors.java' | $(SED) 's:.*/jdk\.vm\.ci/\(.*\)\.java:\1:' | $(TR) '/' '.' > $@ TARGETS += $(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors diff --git a/hotspot/make/hotspot.script b/hotspot/make/hotspot.script index 096be4b3d58..942eafa39d7 100644 --- a/hotspot/make/hotspot.script +++ b/hotspot/make/hotspot.script @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2015, 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 @@ -156,7 +156,7 @@ else export LD_LIBRARY_PATH fi -JPARMS="-XXaltjvm=$MYDIR -Dsun.java.launcher.is_altjvm=true $@ $JAVA_ARGS"; +JPARMS="-XXaltjvm=$MYDIR -Dsun.java.launcher.is_altjvm=true"; # Locate the java launcher LAUNCHER=$JDK/bin/java @@ -181,8 +181,6 @@ init_gdb() { cd `pwd` handle SIGUSR1 nostop noprint handle SIGUSR2 nostop noprint -set args $JPARMS -file $LAUNCHER directory $GDBSRCDIR # Get us to a point where we can set breakpoints in libjvm.so set breakpoint pending on @@ -194,11 +192,10 @@ delete 1 EOF } - case "$MODE" in gdb) init_gdb - $GDB -x $GDBSCR + $GDB -x $GDBSCR --args $LAUNCHER $JPARMS "$@" $JAVA_ARGS rm -f $GDBSCR ;; gud) @@ -219,15 +216,15 @@ case "$MODE" in rm -f $GDBSCR ;; dbx) - $DBX -s $HOME/.dbxrc -c "loadobject -load libjvm.so; stop in JNI_CreateJavaVM; run $JPARMS; delete all" $LAUNCHER + $DBX -s $HOME/.dbxrc -c "loadobject -load libjvm.so; stop in JNI_CreateJavaVM; run $JPARMS $@ $JAVA_ARGS; delete all" $LAUNCHER ;; valgrind) echo Warning: Defaulting to 16Mb heap to make Valgrind run faster, use -Xmx for larger heap echo - $VALGRIND --tool=memcheck --leak-check=yes --num-callers=50 $LAUNCHER -Xmx16m $JPARMS + $VALGRIND --tool=memcheck --leak-check=yes --num-callers=50 $LAUNCHER -Xmx16m $JPARMS "$@" $JAVA_ARGS ;; run) - LD_PRELOAD=$PRELOADING exec $LAUNCHER $JPARMS + LD_PRELOAD=$PRELOADING exec $LAUNCHER $JPARMS "$@" $JAVA_ARGS ;; *) echo Error: Internal error, unknown launch mode \"$MODE\" diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index 3ed22a1da8c..7920596193f 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -61,6 +61,11 @@ else CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1) CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2) CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3) + # Workaround Ubuntu bug where -dumpversion doesn't print a micro version + # https://bugs.launchpad.net/ubuntu/+source/gcc-4.8/+bug/1360404 + ifeq ($(CC_VER_MICRO),) + CC_VER_MICRO := "0" + endif endif ifeq ($(USE_CLANG), true) @@ -224,6 +229,8 @@ ifeq ($(USE_CLANG),) WARNING_FLAGS += -Wtype-limits # GCC < 4.8 don't accept this flag for C++. WARNING_FLAGS += -Wno-format-zero-length + # GCC 4.8 reports less false positives than the older compilers. + WARNING_FLAGS += -Wuninitialized endif endif diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index 1fa9c284d8b..ec0f06d8f65 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -34,7 +34,6 @@ SUNWprivate_1.1 { jio_snprintf; jio_vfprintf; jio_vsnprintf; - fork1; numa_warn; numa_error; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 1fa9c284d8b..ec0f06d8f65 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -34,7 +34,6 @@ SUNWprivate_1.1 { jio_snprintf; jio_vfprintf; jio_vsnprintf; - fork1; numa_warn; numa_error; diff --git a/hotspot/make/linux/makefiles/trace.make b/hotspot/make/linux/makefiles/trace.make index 5cdec9adcb3..7218adc27b3 100644 --- a/hotspot/make/linux/makefiles/trace.make +++ b/hotspot/make/linux/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2015, 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 @@ -82,8 +82,7 @@ all: $(TraceGeneratedFiles) GENERATE_CODE= \ $(QUIETLY) echo $(LOG_INFO) Generating $@; \ - $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@; \ - test -f $@ + $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@ $(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/solaris/makefiles/sparcWorks.make b/hotspot/make/solaris/makefiles/sparcWorks.make index 8a8007f26a5..1706e7cae60 100644 --- a/hotspot/make/solaris/makefiles/sparcWorks.make +++ b/hotspot/make/solaris/makefiles/sparcWorks.make @@ -550,19 +550,6 @@ else #LINK_INTO = LIBJVM endif -# Solaris platforms collect lots of redundant file-ident lines, -# to the point of wasting a significant percentage of file space. -# (The text is stored in ELF .comment sections, contributed by -# all "#pragma ident" directives in header and source files.) -# This command "compresses" the .comment sections simply by -# removing repeated lines. The data can be extracted from -# binaries in the field by using "mcs -p libjvm.so" or the older -# command "what libjvm.so". -LINK_LIB.CXX/POST_HOOK += $(MCS) -c $@ || exit 1; -# (The exit 1 is necessary to cause a build failure if the command fails and -# multiple commands are strung together, and the final semicolon is necessary -# since the hook must terminate itself as a valid command.) - # Also, strip debug and line number information (worth about 1.7Mb). # If we can create .debuginfo files, then the VM is stripped in vm.make # and this macro is not used. diff --git a/hotspot/make/solaris/makefiles/trace.make b/hotspot/make/solaris/makefiles/trace.make index ef4beda149c..ab96c7ffd65 100644 --- a/hotspot/make/solaris/makefiles/trace.make +++ b/hotspot/make/solaris/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2015, 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 @@ -78,8 +78,7 @@ all: $(TraceGeneratedFiles) GENERATE_CODE= \ $(QUIETLY) echo $(LOG_INFO) Generating $@; \ - $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@; \ - test -f $@ + $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@ $(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk index e447560be56..b9d1dfa5894 100644 --- a/hotspot/make/test/JtregNative.gmk +++ b/hotspot/make/test/JtregNative.gmk @@ -45,6 +45,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \ $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \ + $(HOTSPOT_TOPDIR)/test/runtime/SameObject \ # BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native diff --git a/hotspot/make/windows/makefiles/compile.make b/hotspot/make/windows/makefiles/compile.make index aa1063d6eb1..0af2574c251 100644 --- a/hotspot/make/windows/makefiles/compile.make +++ b/hotspot/make/windows/makefiles/compile.make @@ -19,7 +19,7 @@ # 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. -# +# # # Generic compiler settings @@ -54,7 +54,11 @@ CXX=cl.exe # improving the quality of crash log stack traces involving jvm.dll. # These are always used in all compiles -CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 /WX +CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 + +!if "$(WARNINGS_AS_ERRORS)" != "false" +CXX_FLAGS=$(CXX_FLAGS) /WX +!endif # Let's add debug information when Full Debug Symbols is enabled !if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1" @@ -167,7 +171,7 @@ LD_FLAGS= $(LD_FLAGS) /map /debug !endif -!if $(MSC_VER) >= 1600 +!if $(MSC_VER) >= 1600 LD_FLAGS= $(LD_FLAGS) psapi.lib !endif @@ -191,4 +195,3 @@ RC_FLAGS=/D "HS_VER=$(HS_VER)" \ !if "$(MFC_DEBUG)" == "true" RC_FLAGS = $(RC_FLAGS) /D "_DEBUG" !endif - diff --git a/hotspot/make/windows/makefiles/defs.make b/hotspot/make/windows/makefiles/defs.make index ca212624d53..5deb916e49c 100644 --- a/hotspot/make/windows/makefiles/defs.make +++ b/hotspot/make/windows/makefiles/defs.make @@ -31,6 +31,8 @@ SLASH_JAVA ?= J: PATH_SEP = ; +MAKE_ARGS += WARNINGS_AS_ERRORS=$(WARNINGS_AS_ERRORS) + # Need PLATFORM (os-arch combo names) for jdk and hotspot, plus libarch name ifeq ($(ARCH_DATA_MODEL),32) ARCH_DATA_MODEL=32 diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index dabc578fe08..0861f782775 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -14150,6 +14150,7 @@ instruct partialSubtypeCheckVsZero(iRegP_R4 sub, iRegP_R0 super, iRegP_R2 temp, instruct string_compare(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cnt2, iRegI_R0 result, iRegP_R10 tmp1, rFlagsReg cr) %{ + predicate(!CompactStrings); match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); effect(KILL tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); @@ -14165,6 +14166,7 @@ instruct string_compare(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cn instruct string_indexof(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr) %{ + predicate(!CompactStrings); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); @@ -14184,6 +14186,7 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr) %{ + predicate(!CompactStrings); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); @@ -14203,6 +14206,7 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt, iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr) %{ + predicate(!CompactStrings); match(Set result (StrEquals (Binary str1 str2) cnt)); effect(KILL tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); @@ -14218,6 +14222,7 @@ instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt, instruct array_equals(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr) %{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); match(Set result (AryEq ary1 ary2)); effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, KILL cr); diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp index 907370d1385..119d113aac5 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp @@ -483,15 +483,6 @@ int LIR_Assembler::emit_deopt_handler() { return offset; } - -// This is the fast version of java.lang.String.compare; it has not -// OSR-entry and therefore, we generate a slow version for OSR's -void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info) { - __ mov(r2, (address)__FUNCTION__); - __ call_Unimplemented(); -} - - void LIR_Assembler::add_debug_info_for_branch(address adr, CodeEmitInfo* info) { _masm->code_section()->relocate(adr, relocInfo::poll_type); int pc_offset = code_offset(); diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp index 6f213f20a24..0182af2400f 100644 --- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp @@ -79,6 +79,9 @@ define_pd_global(uintx, CMSYoungGenPerWorker, 64*M); // default max size of CMS define_pd_global(uintx, TypeProfileLevel, 111); +// No performance work done here yet. +define_pd_global(bool, CompactStrings, false); + // avoid biased locking while we are bootstrapping the aarch64 build define_pd_global(bool, UseBiasedLocking, false); diff --git a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp index c9467bfb23c..f68c3e854da 100644 --- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp @@ -38,11 +38,11 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) { Unimplemented(); } -void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) { +void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) { Unimplemented(); } -void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { +void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) { Unimplemented(); } diff --git a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp index ba8c3cc31b9..dedabb6729b 100644 --- a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp @@ -62,7 +62,7 @@ static int check_nonzero(const char* xname, int x) { void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, SystemDictionary::WKID klass_id, const char* error_message) { - Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); + InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); KlassHandle klass = SystemDictionary::well_known_klass(klass_id); Register temp = rscratch2; Register temp2 = rscratch1; // used by MacroAssembler::cmpptr diff --git a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp index ef7cacae7a9..b22e5789380 100644 --- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp @@ -1276,7 +1276,7 @@ static void gen_special_dispatch(MacroAssembler* masm, // return to caller // nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, int compile_id, BasicType* in_sig_bt, VMRegPair* in_regs, diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index fac126363a0..e1a5293a826 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -72,6 +72,9 @@ define_pd_global(size_t, CMSYoungGenPerWorker, 16*M); // Default max size of CM define_pd_global(uintx, TypeProfileLevel, 111); +// No performance work done here yet. +define_pd_global(bool, CompactStrings, false); + // Platform dependent flag handling: flags only defined on this platform. #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ \ diff --git a/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp b/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp index cab965e3cc9..13185cc36bf 100644 --- a/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp @@ -38,11 +38,11 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) { Unimplemented(); } -void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) { +void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) { Unimplemented(); } -void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { +void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) { Unimplemented(); } diff --git a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp index 980c043f9e7..fed5e53c206 100644 --- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp @@ -73,7 +73,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj_reg, SystemDictionary::WKID klass_id, Register temp_reg, Register temp2_reg, const char* error_message) { - Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); + InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); KlassHandle klass = SystemDictionary::well_known_klass(klass_id); Label L_ok, L_bad; BLOCK_COMMENT("verify_klass {"); diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index d5f6486056b..51eb16cbe76 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -2054,11 +2054,11 @@ const bool Matcher::match_rule_supported(int opcode) { return (UsePopCountInstruction && VM_Version::has_popcntw()); case Op_StrComp: - return SpecialStringCompareTo; + return SpecialStringCompareTo && !CompactStrings; case Op_StrEquals: - return SpecialStringEquals; + return SpecialStringEquals && !CompactStrings; case Op_StrIndexOf: - return SpecialStringIndexOf; + return SpecialStringIndexOf && !CompactStrings; } return true; // Per default match rules are supported. @@ -5572,7 +5572,6 @@ instruct loadN2P_unscaled(iRegPdst dst, memory mem) %{ instruct loadN2P_klass_unscaled(iRegPdst dst, memory mem) %{ match(Set dst (DecodeNKlass (LoadNKlass mem))); - // SAPJVM GL 2014-05-21 Differs. predicate(Universe::narrow_klass_base() == NULL && Universe::narrow_klass_shift() == 0 && _kids[0]->_leaf->as_Load()->is_unordered()); ins_cost(MEMORY_REF_COST); @@ -10949,7 +10948,7 @@ instruct cmpFastLock(flagsReg crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iR // TODO: PPC port $archOpcode(ppc64Opcode_compound); __ compiler_fast_lock_object($crx$$CondRegister, $oop$$Register, $box$$Register, $tmp3$$Register, $tmp1$$Register, $tmp2$$Register, - UseBiasedLocking && !UseOptoBiasInlining); // SAPJVM MD 2014-11-06 UseOptoBiasInlining + UseBiasedLocking && !UseOptoBiasInlining); // If locking was successfull, crx should indicate 'EQ'. // The compiler generates a branch to the runtime call to // _complete_monitor_locking_Java for the case where crx is 'NE'. @@ -11077,7 +11076,7 @@ instruct string_indexOf_imm1_char(iRegIdst result, iRegPsrc haystack, iRegIsrc h immP needleImm, immL offsetImm, immI_1 needlecntImm, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0, flagsRegCR1 cr1) %{ - predicate(SpecialStringIndexOf); // type check implicit by parameter type, See Matcher::match_rule_supported + predicate(SpecialStringIndexOf && !CompactStrings); // type check implicit by parameter type, See Matcher::match_rule_supported match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm))); effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1); @@ -11120,7 +11119,7 @@ instruct string_indexOf_imm1(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result, TEMP tmp1, TEMP tmp2); // Required for EA: check if it is still a type_array. - predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + predicate(SpecialStringIndexOf && !CompactStrings && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); ins_cost(180); @@ -11167,7 +11166,7 @@ instruct string_indexOf_imm(iRegIdst result, iRegPsrc haystack, rscratch1RegI ha effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6); // Required for EA: check if it is still a type_array. - predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + predicate(SpecialStringIndexOf && !CompactStrings && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); ins_cost(250); @@ -11200,7 +11199,7 @@ instruct string_indexOf(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/ TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6); - predicate(SpecialStringIndexOf); // See Matcher::match_rule_supported. + predicate(SpecialStringIndexOf && !CompactStrings); // See Matcher::match_rule_supported. ins_cost(300); ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. @@ -11224,7 +11223,7 @@ instruct string_equals_imm(iRegPsrc str1, iRegPsrc str2, uimmI15 cntImm, iRegIds match(Set result (StrEquals (Binary str1 str2) cntImm)); effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr6, KILL ctr); - predicate(SpecialStringEquals); // See Matcher::match_rule_supported. + predicate(SpecialStringEquals && !CompactStrings); // See Matcher::match_rule_supported. ins_cost(250); ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. @@ -11247,7 +11246,7 @@ instruct string_equals(iRegPsrc str1, iRegPsrc str2, iRegIsrc cnt, iRegIdst resu match(Set result (StrEquals (Binary str1 str2) cnt)); effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6, KILL ctr); - predicate(SpecialStringEquals); // See Matcher::match_rule_supported. + predicate(SpecialStringEquals && !CompactStrings); // See Matcher::match_rule_supported. ins_cost(300); ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. @@ -11267,6 +11266,7 @@ instruct string_equals(iRegPsrc str1, iRegPsrc str2, iRegIsrc cnt, iRegIdst resu // Use dst register classes if register gets killed, as it is the case for TEMP operands! instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result, iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{ + predicate(!CompactStrings); match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP_DEF result, TEMP tmp, KILL cr0, KILL ctr); ins_cost(300); diff --git a/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp index f075c714748..74e72ba62b6 100644 --- a/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp @@ -61,7 +61,7 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { nativeMovConstReg_at(addr())->set_narrow_oop(no, code()); } } else { - assert((address) (nativeMovConstReg_at(addr())->data()) == x, "data must match"); + guarantee((address) (nativeMovConstReg_at(addr())->data()) == x, "data must match"); } } diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index e6853776063..e89c578e9e7 100644 --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -1701,7 +1701,7 @@ static void gen_special_dispatch(MacroAssembler* masm, // return to caller // nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, - methodHandle method, + const methodHandle& method, int compile_id, BasicType *in_sig_bt, VMRegPair *in_regs, diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index d4fd95ebce1..e2ef96c727c 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -124,6 +124,8 @@ class Assembler : public AbstractAssembler { impdep1_op3 = 0x36, aes3_op3 = 0x36, sha_op3 = 0x36, + bmask_op3 = 0x36, + bshuffle_op3 = 0x36, alignaddr_op3 = 0x36, faligndata_op3 = 0x36, flog3_op3 = 0x36, @@ -194,6 +196,7 @@ class Assembler : public AbstractAssembler { fnegd_opf = 0x06, alignaddr_opf = 0x18, + bmask_opf = 0x19, fadds_opf = 0x41, faddd_opf = 0x42, @@ -204,6 +207,7 @@ class Assembler : public AbstractAssembler { fmuls_opf = 0x49, fmuld_opf = 0x4a, + bshuffle_opf = 0x4c, fdivs_opf = 0x4d, fdivd_opf = 0x4e, @@ -1226,6 +1230,9 @@ public: void edge8n( Register s1, Register s2, Register d ) { vis2_only(); emit_int32( op(arith_op) | rd(d) | op3(edge_op3) | rs1(s1) | opf(edge8n_opf) | rs2(s2)); } + void bmask( Register s1, Register s2, Register d ) { vis2_only(); emit_int32( op(arith_op) | rd(d) | op3(bmask_op3) | rs1(s1) | opf(bmask_opf) | rs2(s2)); } + void bshuffle( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis2_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(bshuffle_op3) | fs1(s1, FloatRegisterImpl::D) | opf(bshuffle_opf) | fs2(s2, FloatRegisterImpl::D)); } + // VIS3 instructions void movstosw( FloatRegister s, Register d ) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); } diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 6efec095dcc..496c9e914da 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -232,118 +232,6 @@ void LIR_Assembler::osr_entry() { } -// Optimized Library calls -// This is the fast version of java.lang.String.compare; it has not -// OSR-entry and therefore, we generate a slow version for OSR's -void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst, CodeEmitInfo* info) { - Register str0 = left->as_register(); - Register str1 = right->as_register(); - - Label Ldone; - - Register result = dst->as_register(); - { - // Get a pointer to the first character of string0 in tmp0 - // and get string0.length() in str0 - // Get a pointer to the first character of string1 in tmp1 - // and get string1.length() in str1 - // Also, get string0.length()-string1.length() in - // o7 and get the condition code set - // Note: some instructions have been hoisted for better instruction scheduling - - Register tmp0 = L0; - Register tmp1 = L1; - Register tmp2 = L2; - - int value_offset = java_lang_String:: value_offset_in_bytes(); // char array - if (java_lang_String::has_offset_field()) { - int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position - int count_offset = java_lang_String:: count_offset_in_bytes(); - __ load_heap_oop(str0, value_offset, tmp0); - __ ld(str0, offset_offset, tmp2); - __ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0); - __ ld(str0, count_offset, str0); - __ sll(tmp2, exact_log2(sizeof(jchar)), tmp2); - } else { - __ load_heap_oop(str0, value_offset, tmp1); - __ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0); - __ ld(tmp1, arrayOopDesc::length_offset_in_bytes(), str0); - } - - // str1 may be null - add_debug_info_for_null_check_here(info); - - if (java_lang_String::has_offset_field()) { - int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position - int count_offset = java_lang_String:: count_offset_in_bytes(); - __ load_heap_oop(str1, value_offset, tmp1); - __ add(tmp0, tmp2, tmp0); - - __ ld(str1, offset_offset, tmp2); - __ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1); - __ ld(str1, count_offset, str1); - __ sll(tmp2, exact_log2(sizeof(jchar)), tmp2); - __ add(tmp1, tmp2, tmp1); - } else { - __ load_heap_oop(str1, value_offset, tmp2); - __ add(tmp2, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1); - __ ld(tmp2, arrayOopDesc::length_offset_in_bytes(), str1); - } - __ subcc(str0, str1, O7); - } - - { - // Compute the minimum of the string lengths, scale it and store it in limit - Register count0 = I0; - Register count1 = I1; - Register limit = L3; - - Label Lskip; - __ sll(count0, exact_log2(sizeof(jchar)), limit); // string0 is shorter - __ br(Assembler::greater, true, Assembler::pt, Lskip); - __ delayed()->sll(count1, exact_log2(sizeof(jchar)), limit); // string1 is shorter - __ bind(Lskip); - - // If either string is empty (or both of them) the result is the difference in lengths - __ cmp(limit, 0); - __ br(Assembler::equal, true, Assembler::pn, Ldone); - __ delayed()->mov(O7, result); // result is difference in lengths - } - - { - // Neither string is empty - Label Lloop; - - Register base0 = L0; - Register base1 = L1; - Register chr0 = I0; - Register chr1 = I1; - Register limit = L3; - - // Shift base0 and base1 to the end of the arrays, negate limit - __ add(base0, limit, base0); - __ add(base1, limit, base1); - __ neg(limit); // limit = -min{string0.length(), string1.length()} - - __ lduh(base0, limit, chr0); - __ bind(Lloop); - __ lduh(base1, limit, chr1); - __ subcc(chr0, chr1, chr0); - __ br(Assembler::notZero, false, Assembler::pn, Ldone); - assert(chr0 == result, "result must be pre-placed"); - __ delayed()->inccc(limit, sizeof(jchar)); - __ br(Assembler::notZero, true, Assembler::pt, Lloop); - __ delayed()->lduh(base0, limit, chr0); - } - - // If strings are equal up to min length, return the length difference. - __ mov(O7, result); - - // Otherwise, return the difference between the first mismatched chars. - __ bind(Ldone); -} - - // -------------------------------------------------------------------------------------------- void LIR_Assembler::monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register hdr, int monitor_no) { diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp index 36f660b554b..06867066fc1 100644 --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp @@ -86,6 +86,8 @@ define_pd_global(size_t, CMSYoungGenPerWorker, 16*M); // default max size of CM define_pd_global(uintx, TypeProfileLevel, 111); +define_pd_global(bool, CompactStrings, true); + #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ \ product(intx, UseVIS, 99, \ diff --git a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp index 10da55791d3..45b27ab0a78 100644 --- a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp @@ -66,6 +66,25 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) { } } +void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) { + address pc = _instructions->start() + pc_offset; + if (HotSpotMetaspaceConstantImpl::compressed(constant)) { +#ifdef _LP64 + NativeMovConstReg32* move = nativeMovConstReg32_at(pc); + narrowKlass narrowOop = record_narrow_metadata_reference(constant); + move->set_data((intptr_t)narrowOop); + TRACE_jvmci_3("relocating (narrow metaspace constant) at %p/%p", pc, narrowOop); +#else + fatal("compressed Klass* on 32bit"); +#endif + } else { + NativeMovConstReg* move = nativeMovConstReg_at(pc); + Metadata* reference = record_metadata_reference(constant); + move->set_data((intptr_t)reference); + TRACE_jvmci_3("relocating (metaspace constant) at %p/%p", pc, reference); + } +} + void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) { address pc = _instructions->start() + pc_offset; NativeInstruction* inst = nativeInstruction_at(pc); @@ -87,10 +106,6 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset } } -void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { - fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp"); -} - void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { address pc = (address) inst; if (inst->is_call()) { @@ -168,16 +183,25 @@ void CodeInstaller::pd_relocate_poll(address pc, jint mark) { // convert JVMCI register indices (as used in oop maps) to HotSpot registers VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) { - if (jvmci_reg < RegisterImpl::number_of_registers) { + // JVMCI Registers are numbered as follows: + // 0..31: Thirty-two General Purpose registers (CPU Registers) + // 32..63: Thirty-two single precision float registers + // 64..95: Thirty-two double precision float registers + // 96..111: Sixteen quad precision float registers + if (jvmci_reg < 32) { return as_Register(jvmci_reg)->as_VMReg(); } else { - jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers; - floatRegisterNumber += MAX2(0, floatRegisterNumber-32); // Beginning with f32, only every second register is going to be addressed - if (floatRegisterNumber < FloatRegisterImpl::number_of_registers) { - return as_FloatRegister(floatRegisterNumber)->as_VMReg(); + jint floatRegisterNumber; + if(jvmci_reg < 64) { // Single precision + floatRegisterNumber = jvmci_reg - 32; + } else if(jvmci_reg < 96) { + floatRegisterNumber = 2 * (jvmci_reg - 64); + } else if(jvmci_reg < 112) { + floatRegisterNumber = 4 * (jvmci_reg - 96); + } else { + fatal("Unknown jvmci register"); } - ShouldNotReachHere(); - return NULL; + return as_FloatRegister(floatRegisterNumber)->as_VMReg(); } } diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp index 2647d327bd5..a6d5cd68e47 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -44,6 +44,9 @@ #include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/heapRegion.hpp" #endif // INCLUDE_ALL_GCS +#ifdef COMPILER2 +#include "opto/intrinsicnode.hpp" +#endif #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -4253,27 +4256,385 @@ void MacroAssembler::reinit_heapbase() { } } -// Compare char[] arrays aligned to 4 bytes. -void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, - Register limit, Register result, - Register chr1, Register chr2, Label& Ldone) { - Label Lvector, Lloop; - assert(chr1 == result, "should be the same"); +#ifdef COMPILER2 - // Note: limit contains number of bytes (2*char_elements) != 0. - andcc(limit, 0x2, chr1); // trailing character ? +// Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure. +void MacroAssembler::string_compress_16(Register src, Register dst, Register cnt, Register result, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, + FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone) { + Label Lloop, Lslow; + assert(UseVIS >= 3, "VIS3 is required"); + assert_different_registers(src, dst, cnt, tmp1, tmp2, tmp3, tmp4, result); + assert_different_registers(ftmp1, ftmp2, ftmp3); + + // Check if cnt >= 8 (= 16 bytes) + cmp(cnt, 8); + br(Assembler::less, false, Assembler::pn, Lslow); + delayed()->mov(cnt, result); // copy count + + // Check for 8-byte alignment of src and dst + or3(src, dst, tmp1); + andcc(tmp1, 7, G0); + br(Assembler::notZero, false, Assembler::pn, Lslow); + delayed()->nop(); + + // Set mask for bshuffle instruction + Register mask = tmp4; + set(0x13579bdf, mask); + bmask(mask, G0, G0); + + // Set mask to 0xff00 ff00 ff00 ff00 to check for non-latin1 characters + Assembler::sethi(0xff00fc00, mask); // mask = 0x0000 0000 ff00 fc00 + add(mask, 0x300, mask); // mask = 0x0000 0000 ff00 ff00 + sllx(mask, 32, tmp1); // tmp1 = 0xff00 ff00 0000 0000 + or3(mask, tmp1, mask); // mask = 0xff00 ff00 ff00 ff00 + + // Load first 8 bytes + ldx(src, 0, tmp1); + + bind(Lloop); + // Load next 8 bytes + ldx(src, 8, tmp2); + + // Check for non-latin1 character by testing if the most significant byte of a char is set. + // Although we have to move the data between integer and floating point registers, this is + // still faster than the corresponding VIS instructions (ford/fand/fcmpd). + or3(tmp1, tmp2, tmp3); + btst(tmp3, mask); + // annul zeroing if branch is not taken to preserve original count + brx(Assembler::notZero, true, Assembler::pn, Ldone); + delayed()->mov(G0, result); // 0 - failed + + // Move bytes into float register + movxtod(tmp1, ftmp1); + movxtod(tmp2, ftmp2); + + // Compress by copying one byte per char from ftmp1 and ftmp2 to ftmp3 + bshuffle(ftmp1, ftmp2, ftmp3); + stf(FloatRegisterImpl::D, ftmp3, dst, 0); + + // Increment addresses and decrement count + inc(src, 16); + inc(dst, 8); + dec(cnt, 8); + + cmp(cnt, 8); + // annul LDX if branch is not taken to prevent access past end of string + br(Assembler::greaterEqual, true, Assembler::pt, Lloop); + delayed()->ldx(src, 0, tmp1); + + // Fallback to slow version + bind(Lslow); +} + +// Compress char[] to byte[]. Return 0 on failure. +void MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register result, Register tmp, Label& Ldone) { + Label Lloop; + assert_different_registers(src, dst, cnt, tmp, result); + + lduh(src, 0, tmp); + + bind(Lloop); + inc(src, sizeof(jchar)); + cmp(tmp, 0xff); + // annul zeroing if branch is not taken to preserve original count + br(Assembler::greater, true, Assembler::pn, Ldone); // don't check xcc + delayed()->mov(G0, result); // 0 - failed + deccc(cnt); + stb(tmp, dst, 0); + inc(dst); + // annul LDUH if branch is not taken to prevent access past end of string + br(Assembler::notZero, true, Assembler::pt, Lloop); + delayed()->lduh(src, 0, tmp); // hoisted +} + +// Inflate byte[] to char[] by inflating 16 bytes at once. +void MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt, Register tmp, + FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone) { + Label Lloop, Lslow; + assert(UseVIS >= 3, "VIS3 is required"); + assert_different_registers(src, dst, cnt, tmp); + assert_different_registers(ftmp1, ftmp2, ftmp3, ftmp4); + + // Check if cnt >= 8 (= 16 bytes) + cmp(cnt, 8); + br(Assembler::less, false, Assembler::pn, Lslow); + delayed()->nop(); + + // Check for 8-byte alignment of src and dst + or3(src, dst, tmp); + andcc(tmp, 7, G0); + br(Assembler::notZero, false, Assembler::pn, Lslow); + // Initialize float register to zero + FloatRegister zerof = ftmp4; + delayed()->fzero(FloatRegisterImpl::D, zerof); + + // Load first 8 bytes + ldf(FloatRegisterImpl::D, src, 0, ftmp1); + + bind(Lloop); + inc(src, 8); + dec(cnt, 8); + + // Inflate the string by interleaving each byte from the source array + // with a zero byte and storing the result in the destination array. + fpmerge(zerof, ftmp1->successor(), ftmp2); + stf(FloatRegisterImpl::D, ftmp2, dst, 8); + fpmerge(zerof, ftmp1, ftmp3); + stf(FloatRegisterImpl::D, ftmp3, dst, 0); + + inc(dst, 16); + + cmp(cnt, 8); + // annul LDX if branch is not taken to prevent access past end of string + br(Assembler::greaterEqual, true, Assembler::pt, Lloop); + delayed()->ldf(FloatRegisterImpl::D, src, 0, ftmp1); + + // Fallback to slow version + bind(Lslow); +} + +// Inflate byte[] to char[]. +void MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone) { + Label Loop; + assert_different_registers(src, dst, cnt, tmp); + + ldub(src, 0, tmp); + bind(Loop); + inc(src); + deccc(cnt); + sth(tmp, dst, 0); + inc(dst, sizeof(jchar)); + // annul LDUB if branch is not taken to prevent access past end of string + br(Assembler::notZero, true, Assembler::pt, Loop); + delayed()->ldub(src, 0, tmp); // hoisted +} + +void MacroAssembler::string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, + Register tmp1, Register tmp2, + Register result, int ae) { + Label Ldone, Lloop; + assert_different_registers(str1, str2, cnt1, cnt2, tmp1, result); + int stride1, stride2; + + // Note: Making use of the fact that compareTo(a, b) == -compareTo(b, a) + // we interchange str1 and str2 in the UL case and negate the result. + // Like this, str1 is always latin1 encoded, expect for the UU case. + + if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) { + srl(cnt2, 1, cnt2); + } + + // See if the lengths are different, and calculate min in cnt1. + // Save diff in case we need it for a tie-breaker. + Label Lskip; + Register diff = tmp1; + subcc(cnt1, cnt2, diff); + br(Assembler::greater, true, Assembler::pt, Lskip); + // cnt2 is shorter, so use its count: + delayed()->mov(cnt2, cnt1); + bind(Lskip); + + // Rename registers + Register limit1 = cnt1; + Register limit2 = limit1; + Register chr1 = result; + Register chr2 = cnt2; + if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) { + // We need an additional register to keep track of two limits + assert_different_registers(str1, str2, cnt1, cnt2, tmp1, tmp2, result); + limit2 = tmp2; + } + + // Is the minimum length zero? + cmp(limit1, (int)0); // use cast to resolve overloading ambiguity + br(Assembler::equal, true, Assembler::pn, Ldone); + // result is difference in lengths + if (ae == StrIntrinsicNode::UU) { + delayed()->sra(diff, 1, result); // Divide by 2 to get number of chars + } else { + delayed()->mov(diff, result); + } + + // Load first characters + if (ae == StrIntrinsicNode::LL) { + stride1 = stride2 = sizeof(jbyte); + ldub(str1, 0, chr1); + ldub(str2, 0, chr2); + } else if (ae == StrIntrinsicNode::UU) { + stride1 = stride2 = sizeof(jchar); + lduh(str1, 0, chr1); + lduh(str2, 0, chr2); + } else { + stride1 = sizeof(jbyte); + stride2 = sizeof(jchar); + ldub(str1, 0, chr1); + lduh(str2, 0, chr2); + } + + // Compare first characters + subcc(chr1, chr2, chr1); + br(Assembler::notZero, false, Assembler::pt, Ldone); + assert(chr1 == result, "result must be pre-placed"); + delayed()->nop(); + + // Check if the strings start at same location + cmp(str1, str2); + brx(Assembler::equal, true, Assembler::pn, Ldone); + delayed()->mov(G0, result); // result is zero + + // We have no guarantee that on 64 bit the higher half of limit is 0 + signx(limit1); + + // Get limit + if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) { + sll(limit1, 1, limit2); + subcc(limit2, stride2, chr2); + } + subcc(limit1, stride1, chr1); + br(Assembler::zero, true, Assembler::pn, Ldone); + // result is difference in lengths + if (ae == StrIntrinsicNode::UU) { + delayed()->sra(diff, 1, result); // Divide by 2 to get number of chars + } else { + delayed()->mov(diff, result); + } + + // Shift str1 and str2 to the end of the arrays, negate limit + add(str1, limit1, str1); + add(str2, limit2, str2); + neg(chr1, limit1); // limit1 = -(limit1-stride1) + if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) { + neg(chr2, limit2); // limit2 = -(limit2-stride2) + } + + // Compare the rest of the characters + if (ae == StrIntrinsicNode::UU) { + lduh(str1, limit1, chr1); + } else { + ldub(str1, limit1, chr1); + } + + bind(Lloop); + if (ae == StrIntrinsicNode::LL) { + ldub(str2, limit2, chr2); + } else { + lduh(str2, limit2, chr2); + } + + subcc(chr1, chr2, chr1); + br(Assembler::notZero, false, Assembler::pt, Ldone); + assert(chr1 == result, "result must be pre-placed"); + delayed()->inccc(limit1, stride1); + if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) { + inccc(limit2, stride2); + } + + // annul LDUB if branch is not taken to prevent access past end of string + br(Assembler::notZero, true, Assembler::pt, Lloop); + if (ae == StrIntrinsicNode::UU) { + delayed()->lduh(str1, limit2, chr1); + } else { + delayed()->ldub(str1, limit1, chr1); + } + + // If strings are equal up to min length, return the length difference. + if (ae == StrIntrinsicNode::UU) { + // Divide by 2 to get number of chars + sra(diff, 1, result); + } else { + mov(diff, result); + } + + // Otherwise, return the difference between the first mismatched chars. + bind(Ldone); + if(ae == StrIntrinsicNode::UL) { + // Negate result (see note above) + neg(result); + } +} + +void MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2, + Register limit, Register tmp, Register result, bool is_byte) { + Label Ldone, Lvector, Lloop; + assert_different_registers(ary1, ary2, limit, tmp, result); + + int length_offset = arrayOopDesc::length_offset_in_bytes(); + int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR); + + if (is_array_equ) { + // return true if the same array + cmp(ary1, ary2); + brx(Assembler::equal, true, Assembler::pn, Ldone); + delayed()->add(G0, 1, result); // equal + + br_null(ary1, true, Assembler::pn, Ldone); + delayed()->mov(G0, result); // not equal + + br_null(ary2, true, Assembler::pn, Ldone); + delayed()->mov(G0, result); // not equal + + // load the lengths of arrays + ld(Address(ary1, length_offset), limit); + ld(Address(ary2, length_offset), tmp); + + // return false if the two arrays are not equal length + cmp(limit, tmp); + br(Assembler::notEqual, true, Assembler::pn, Ldone); + delayed()->mov(G0, result); // not equal + } + + cmp_zero_and_br(Assembler::zero, limit, Ldone, true, Assembler::pn); + delayed()->add(G0, 1, result); // zero-length arrays are equal + + if (is_array_equ) { + // load array addresses + add(ary1, base_offset, ary1); + add(ary2, base_offset, ary2); + } else { + // We have no guarantee that on 64 bit the higher half of limit is 0 + signx(limit); + } + + if (is_byte) { + Label Lskip; + // check for trailing byte + andcc(limit, 0x1, tmp); + br(Assembler::zero, false, Assembler::pt, Lskip); + delayed()->nop(); + + // compare the trailing byte + sub(limit, sizeof(jbyte), limit); + ldub(ary1, limit, result); + ldub(ary2, limit, tmp); + cmp(result, tmp); + br(Assembler::notEqual, true, Assembler::pt, Ldone); + delayed()->mov(G0, result); // not equal + + // only one byte? + cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn); + delayed()->add(G0, 1, result); // zero-length arrays are equal + bind(Lskip); + } else if (is_array_equ) { + // set byte count + sll(limit, exact_log2(sizeof(jchar)), limit); + } + + // check for trailing character + andcc(limit, 0x2, tmp); br(Assembler::zero, false, Assembler::pt, Lvector); delayed()->nop(); // compare the trailing char sub(limit, sizeof(jchar), limit); - lduh(ary1, limit, chr1); - lduh(ary2, limit, chr2); - cmp(chr1, chr2); + lduh(ary1, limit, result); + lduh(ary2, limit, tmp); + cmp(result, tmp); br(Assembler::notEqual, true, Assembler::pt, Ldone); delayed()->mov(G0, result); // not equal - // only one char ? + // only one char? cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn); delayed()->add(G0, 1, result); // zero-length arrays are equal @@ -4284,21 +4645,23 @@ void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, add(ary2, limit, ary2); neg(limit, limit); - lduw(ary1, limit, chr1); + lduw(ary1, limit, result); bind(Lloop); - lduw(ary2, limit, chr2); - cmp(chr1, chr2); + lduw(ary2, limit, tmp); + cmp(result, tmp); br(Assembler::notEqual, true, Assembler::pt, Ldone); delayed()->mov(G0, result); // not equal inccc(limit, 2*sizeof(jchar)); // annul LDUW if branch is not taken to prevent access past end of array br(Assembler::notZero, true, Assembler::pt, Lloop); - delayed()->lduw(ary1, limit, chr1); // hoisted + delayed()->lduw(ary1, limit, result); // hoisted - // Caller should set it: - // add(G0, 1, result); // equals + add(G0, 1, result); // equals + bind(Ldone); } +#endif + // Use BIS for zeroing (count is in bytes). void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) { assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing"); diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp index 22f56b999bc..792a493bc01 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp @@ -1433,10 +1433,31 @@ public: void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2); void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2); - // Compare char[] arrays aligned to 4 bytes. - void char_arrays_equals(Register ary1, Register ary2, - Register limit, Register result, - Register chr1, Register chr2, Label& Ldone); +#ifdef COMPILER2 + // Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure. + void string_compress_16(Register src, Register dst, Register cnt, Register result, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, + FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone); + + // Compress char[] to byte[]. Return 0 on failure. + void string_compress(Register src, Register dst, Register cnt, Register tmp, Register result, Label& Ldone); + + // Inflate byte[] to char[] by inflating 16 bytes at once. + void string_inflate_16(Register src, Register dst, Register cnt, Register tmp, + FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone); + + // Inflate byte[] to char[]. + void string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone); + + void string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, + Register tmp1, Register tmp2, + Register result, int ae); + + void array_equals(bool is_array_equ, Register ary1, Register ary2, + Register limit, Register tmp, Register result, bool is_byte); +#endif + // Use BIS for zeroing void bis_zeroing(Register to, Register count, Register temp, Label& Ldone); diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index 5246059b470..4d51de2921a 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -69,7 +69,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj_reg, SystemDictionary::WKID klass_id, Register temp_reg, Register temp2_reg, const char* error_message) { - Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); + InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); KlassHandle klass = SystemDictionary::well_known_klass(klass_id); bool did_save = false; if (temp_reg == noreg || temp2_reg == noreg) { diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp index c7b89b110e9..3342f51388e 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp @@ -60,7 +60,7 @@ void NativeInstruction::verify_data64_sethi(address instaddr, intptr_t x) { masm.patchable_sethi(x, destreg); int len = buffer - masm.pc(); for (int i = 0; i < len; i++) { - assert(instaddr[i] == buffer[i], "instructions must match"); + guarantee(instaddr[i] == buffer[i], "instructions must match"); } } @@ -417,6 +417,67 @@ void NativeMovConstReg::test() { //------------------------------------------------------------------- +void NativeMovConstReg32::verify() { + NativeInstruction::verify(); + // make sure code pattern is actually a "set_metadata" synthetic instruction + // see MacroAssembler::set_oop() + int i0 = long_at(sethi_offset); + int i1 = long_at(add_offset); + + // verify the pattern "sethi %hi22(imm), reg ; add reg, %lo10(imm), reg" + Register rd = inv_rd(i0); + if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) { + fatal("not a set_metadata"); + } +} + + +void NativeMovConstReg32::print() { + tty->print_cr(INTPTR_FORMAT ": mov reg, " INTPTR_FORMAT, instruction_address(), data()); +} + + +intptr_t NativeMovConstReg32::data() const { + return data32(long_at(sethi_offset), long_at(add_offset)); +} + + +void NativeMovConstReg32::set_data(intptr_t x) { + set_long_at(sethi_offset, set_data32_sethi( long_at(sethi_offset), x)); + set_long_at(add_offset, set_data32_simm13( long_at(add_offset), x)); + + // also store the value into an oop_Relocation cell, if any + CodeBlob* cb = CodeCache::find_blob(instruction_address()); + nmethod* nm = cb ? cb->as_nmethod_or_null() : NULL; + if (nm != NULL) { + RelocIterator iter(nm, instruction_address(), next_instruction_address()); + oop* oop_addr = NULL; + Metadata** metadata_addr = NULL; + while (iter.next()) { + if (iter.type() == relocInfo::oop_type) { + oop_Relocation *r = iter.oop_reloc(); + if (oop_addr == NULL) { + oop_addr = r->oop_addr(); + *oop_addr = cast_to_oop(x); + } else { + assert(oop_addr == r->oop_addr(), "must be only one set-oop here"); + } + } + if (iter.type() == relocInfo::metadata_type) { + metadata_Relocation *r = iter.metadata_reloc(); + if (metadata_addr == NULL) { + metadata_addr = r->metadata_addr(); + *metadata_addr = (Metadata*)x; + } else { + assert(metadata_addr == r->metadata_addr(), "must be only one set-metadata here"); + } + } + } + } +} + +//------------------------------------------------------------------- + void NativeMovConstRegPatching::verify() { NativeInstruction::verify(); // Make sure code pattern is sethi/nop/add. diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp index 44e0470133e..a5f04a8f5b9 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp @@ -518,6 +518,46 @@ class NativeFarCall: public NativeInstruction { #endif // _LP64 +// An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions +// (used to manipulate inlined data references, etc.) +// set_metadata imm, reg +// == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg +class NativeMovConstReg32; +inline NativeMovConstReg32* nativeMovConstReg32_at(address address); +class NativeMovConstReg32: public NativeInstruction { + public: + enum Sparc_specific_constants { + sethi_offset = 0, + add_offset = 4, + instruction_size = 8 + }; + + address instruction_address() const { return addr_at(0); } + address next_instruction_address() const { return addr_at(instruction_size); } + + // (The [set_]data accessor respects oop_type relocs also.) + intptr_t data() const; + void set_data(intptr_t x); + + // report the destination register + Register destination() { return inv_rd(long_at(sethi_offset)); } + + void verify(); + void print(); + + // unit test stuff + static void test(); + + // Creation + friend inline NativeMovConstReg32* nativeMovConstReg32_at(address address) { + NativeMovConstReg32* test = (NativeMovConstReg32*)address; + #ifdef ASSERT + test->verify(); + #endif + return test; + } +}; + // An interface for accessing/manipulating native set_metadata imm, reg instructions. // (used to manipulate inlined data references, etc.) // set_metadata imm, reg diff --git a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp index a9f2421c0fb..9c70bd0ef4d 100644 --- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp @@ -84,7 +84,7 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { inst &= ~Assembler::simm( -1, 13); inst |= Assembler::simm(simm13, 13); if (verify_only) { - assert(ip->long_at(0) == inst, "instructions must match"); + guarantee(ip->long_at(0) == inst, "instructions must match"); } else { ip->set_long_at(0, inst); } @@ -102,15 +102,15 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { inst &= ~Assembler::hi22(-1); inst |= Assembler::hi22((intptr_t)np); if (verify_only) { - assert(ip->long_at(0) == inst, "instructions must match"); + guarantee(ip->long_at(0) == inst, "instructions must match"); } else { ip->set_long_at(0, inst); } inst2 = ip->long_at( NativeInstruction::nop_instruction_size ); guarantee(Assembler::inv_op(inst2)==Assembler::arith_op, "arith op"); if (verify_only) { - assert(ip->long_at(NativeInstruction::nop_instruction_size) == NativeInstruction::set_data32_simm13( inst2, (intptr_t)np), - "instructions must match"); + guarantee(ip->long_at(NativeInstruction::nop_instruction_size) == NativeInstruction::set_data32_simm13( inst2, (intptr_t)np), + "instructions must match"); } else { ip->set_long_at(NativeInstruction::nop_instruction_size, NativeInstruction::set_data32_simm13( inst2, (intptr_t)np)); } @@ -127,7 +127,7 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { inst |= Assembler::hi22((intptr_t)x); // (ignore offset; it doesn't play into the sethi) if (verify_only) { - assert(ip->long_at(0) == inst, "instructions must match"); + guarantee(ip->long_at(0) == inst, "instructions must match"); } else { ip->set_long_at(0, inst); } diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index 449488b94c9..0c78b651e44 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -1955,7 +1955,7 @@ static void gen_special_dispatch(MacroAssembler* masm, // return to caller // nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, int compile_id, BasicType* in_sig_bt, VMRegPair* in_regs, diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 886a9c30d02..5d26b664175 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -2905,232 +2905,6 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{ __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst); %} - - enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{ - Label Ldone, Lloop; - MacroAssembler _masm(&cbuf); - - Register str1_reg = reg_to_register_object($str1$$reg); - Register str2_reg = reg_to_register_object($str2$$reg); - Register cnt1_reg = reg_to_register_object($cnt1$$reg); - Register cnt2_reg = reg_to_register_object($cnt2$$reg); - Register result_reg = reg_to_register_object($result$$reg); - - assert(result_reg != str1_reg && - result_reg != str2_reg && - result_reg != cnt1_reg && - result_reg != cnt2_reg , - "need different registers"); - - // Compute the minimum of the string lengths(str1_reg) and the - // difference of the string lengths (stack) - - // See if the lengths are different, and calculate min in str1_reg. - // Stash diff in O7 in case we need it for a tie-breaker. - Label Lskip; - __ subcc(cnt1_reg, cnt2_reg, O7); - __ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit - __ br(Assembler::greater, true, Assembler::pt, Lskip); - // cnt2 is shorter, so use its count: - __ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit - __ bind(Lskip); - - // reallocate cnt1_reg, cnt2_reg, result_reg - // Note: limit_reg holds the string length pre-scaled by 2 - Register limit_reg = cnt1_reg; - Register chr2_reg = cnt2_reg; - Register chr1_reg = result_reg; - // str{12} are the base pointers - - // Is the minimum length zero? - __ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity - __ br(Assembler::equal, true, Assembler::pn, Ldone); - __ delayed()->mov(O7, result_reg); // result is difference in lengths - - // Load first characters - __ lduh(str1_reg, 0, chr1_reg); - __ lduh(str2_reg, 0, chr2_reg); - - // Compare first characters - __ subcc(chr1_reg, chr2_reg, chr1_reg); - __ br(Assembler::notZero, false, Assembler::pt, Ldone); - assert(chr1_reg == result_reg, "result must be pre-placed"); - __ delayed()->nop(); - - { - // Check after comparing first character to see if strings are equivalent - Label LSkip2; - // Check if the strings start at same location - __ cmp(str1_reg, str2_reg); - __ brx(Assembler::notEqual, true, Assembler::pt, LSkip2); - __ delayed()->nop(); - - // Check if the length difference is zero (in O7) - __ cmp(G0, O7); - __ br(Assembler::equal, true, Assembler::pn, Ldone); - __ delayed()->mov(G0, result_reg); // result is zero - - // Strings might not be equal - __ bind(LSkip2); - } - - // We have no guarantee that on 64 bit the higher half of limit_reg is 0 - __ signx(limit_reg); - - __ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg); - __ br(Assembler::equal, true, Assembler::pn, Ldone); - __ delayed()->mov(O7, result_reg); // result is difference in lengths - - // Shift str1_reg and str2_reg to the end of the arrays, negate limit - __ add(str1_reg, limit_reg, str1_reg); - __ add(str2_reg, limit_reg, str2_reg); - __ neg(chr1_reg, limit_reg); // limit = -(limit-2) - - // Compare the rest of the characters - __ lduh(str1_reg, limit_reg, chr1_reg); - __ bind(Lloop); - // __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted - __ lduh(str2_reg, limit_reg, chr2_reg); - __ subcc(chr1_reg, chr2_reg, chr1_reg); - __ br(Assembler::notZero, false, Assembler::pt, Ldone); - assert(chr1_reg == result_reg, "result must be pre-placed"); - __ delayed()->inccc(limit_reg, sizeof(jchar)); - // annul LDUH if branch is not taken to prevent access past end of string - __ br(Assembler::notZero, true, Assembler::pt, Lloop); - __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted - - // If strings are equal up to min length, return the length difference. - __ mov(O7, result_reg); - - // Otherwise, return the difference between the first mismatched chars. - __ bind(Ldone); - %} - -enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{ - Label Lchar, Lchar_loop, Ldone; - MacroAssembler _masm(&cbuf); - - Register str1_reg = reg_to_register_object($str1$$reg); - Register str2_reg = reg_to_register_object($str2$$reg); - Register cnt_reg = reg_to_register_object($cnt$$reg); - Register tmp1_reg = O7; - Register result_reg = reg_to_register_object($result$$reg); - - assert(result_reg != str1_reg && - result_reg != str2_reg && - result_reg != cnt_reg && - result_reg != tmp1_reg , - "need different registers"); - - __ cmp(str1_reg, str2_reg); //same char[] ? - __ brx(Assembler::equal, true, Assembler::pn, Ldone); - __ delayed()->add(G0, 1, result_reg); - - __ cmp_zero_and_br(Assembler::zero, cnt_reg, Ldone, true, Assembler::pn); - __ delayed()->add(G0, 1, result_reg); // count == 0 - - //rename registers - Register limit_reg = cnt_reg; - Register chr1_reg = result_reg; - Register chr2_reg = tmp1_reg; - - // We have no guarantee that on 64 bit the higher half of limit_reg is 0 - __ signx(limit_reg); - - //check for alignment and position the pointers to the ends - __ or3(str1_reg, str2_reg, chr1_reg); - __ andcc(chr1_reg, 0x3, chr1_reg); - // notZero means at least one not 4-byte aligned. - // We could optimize the case when both arrays are not aligned - // but it is not frequent case and it requires additional checks. - __ br(Assembler::notZero, false, Assembler::pn, Lchar); // char by char compare - __ delayed()->sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); // set byte count - - // Compare char[] arrays aligned to 4 bytes. - __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, - chr1_reg, chr2_reg, Ldone); - __ ba(Ldone); - __ delayed()->add(G0, 1, result_reg); - - // char by char compare - __ bind(Lchar); - __ add(str1_reg, limit_reg, str1_reg); - __ add(str2_reg, limit_reg, str2_reg); - __ neg(limit_reg); //negate count - - __ lduh(str1_reg, limit_reg, chr1_reg); - // Lchar_loop - __ bind(Lchar_loop); - __ lduh(str2_reg, limit_reg, chr2_reg); - __ cmp(chr1_reg, chr2_reg); - __ br(Assembler::notEqual, true, Assembler::pt, Ldone); - __ delayed()->mov(G0, result_reg); //not equal - __ inccc(limit_reg, sizeof(jchar)); - // annul LDUH if branch is not taken to prevent access past end of string - __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); - __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted - - __ add(G0, 1, result_reg); //equal - - __ bind(Ldone); - %} - -enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, notemp_iRegI result) %{ - Label Lvector, Ldone, Lloop; - MacroAssembler _masm(&cbuf); - - Register ary1_reg = reg_to_register_object($ary1$$reg); - Register ary2_reg = reg_to_register_object($ary2$$reg); - Register tmp1_reg = reg_to_register_object($tmp1$$reg); - Register tmp2_reg = O7; - Register result_reg = reg_to_register_object($result$$reg); - - int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); - - // return true if the same array - __ cmp(ary1_reg, ary2_reg); - __ brx(Assembler::equal, true, Assembler::pn, Ldone); - __ delayed()->add(G0, 1, result_reg); // equal - - __ br_null(ary1_reg, true, Assembler::pn, Ldone); - __ delayed()->mov(G0, result_reg); // not equal - - __ br_null(ary2_reg, true, Assembler::pn, Ldone); - __ delayed()->mov(G0, result_reg); // not equal - - //load the lengths of arrays - __ ld(Address(ary1_reg, length_offset), tmp1_reg); - __ ld(Address(ary2_reg, length_offset), tmp2_reg); - - // return false if the two arrays are not equal length - __ cmp(tmp1_reg, tmp2_reg); - __ br(Assembler::notEqual, true, Assembler::pn, Ldone); - __ delayed()->mov(G0, result_reg); // not equal - - __ cmp_zero_and_br(Assembler::zero, tmp1_reg, Ldone, true, Assembler::pn); - __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal - - // load array addresses - __ add(ary1_reg, base_offset, ary1_reg); - __ add(ary2_reg, base_offset, ary2_reg); - - // renaming registers - Register chr1_reg = result_reg; // for characters in ary1 - Register chr2_reg = tmp2_reg; // for characters in ary2 - Register limit_reg = tmp1_reg; // length - - // set byte count - __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); - - // Compare char[] arrays aligned to 4 bytes. - __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, - chr1_reg, chr2_reg, Ldone); - __ add(G0, 1, result_reg); // equals - - __ bind(Ldone); - %} - enc_class enc_rethrow() %{ cbuf.set_insts_mark(); Register temp_reg = G3; @@ -10275,33 +10049,204 @@ instruct clear_array_bis_2(g1RegX cnt, o0RegP base, iRegX tmp, Universe dummy, f ins_pipe(long_memory_op); %} -instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, - o7RegI tmp, flagsReg ccr) %{ +instruct string_compareL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, + o7RegI tmp, flagsReg ccr) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp); ins_cost(300); - format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} - ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) ); + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + $tmp$$Register, $tmp$$Register, + $result$$Register, StrIntrinsicNode::LL); + %} ins_pipe(long_memory_op); %} -instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, - o7RegI tmp, flagsReg ccr) %{ +instruct string_compareU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, + o7RegI tmp, flagsReg ccr) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp); + ins_cost(300); + format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + $tmp$$Register, $tmp$$Register, + $result$$Register, StrIntrinsicNode::UU); + %} + ins_pipe(long_memory_op); +%} + +instruct string_compareLU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, + o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2); + ins_cost(300); + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1,$tmp2" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + $tmp1$$Register, $tmp2$$Register, + $result$$Register, StrIntrinsicNode::LU); + %} + ins_pipe(long_memory_op); +%} + +instruct string_compareUL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, + o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2); + ins_cost(300); + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1,$tmp2" %} + ins_encode %{ + __ string_compare($str2$$Register, $str1$$Register, + $cnt2$$Register, $cnt1$$Register, + $tmp1$$Register, $tmp2$$Register, + $result$$Register, StrIntrinsicNode::UL); + %} + ins_pipe(long_memory_op); +%} + +instruct string_equalsL(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, + o7RegI tmp, flagsReg ccr) %{ + predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (StrEquals (Binary str1 str2) cnt)); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr); ins_cost(300); - format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %} - ins_encode( enc_String_Equals(str1, str2, cnt, result) ); + format %{ "String Equals byte[] $str1,$str2,$cnt -> $result // KILL $tmp" %} + ins_encode %{ + __ array_equals(false, $str1$$Register, $str2$$Register, + $cnt$$Register, $tmp$$Register, + $result$$Register, true /* byte */); + %} ins_pipe(long_memory_op); %} -instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, - o7RegI tmp2, flagsReg ccr) %{ +instruct string_equalsU(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, + o7RegI tmp, flagsReg ccr) %{ + predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr); + ins_cost(300); + format %{ "String Equals char[] $str1,$str2,$cnt -> $result // KILL $tmp" %} + ins_encode %{ + __ array_equals(false, $str1$$Register, $str2$$Register, + $cnt$$Register, $tmp$$Register, + $result$$Register, false /* byte */); + %} + ins_pipe(long_memory_op); +%} + +instruct array_equalsB(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, + o7RegI tmp2, flagsReg ccr) %{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (AryEq ary1 ary2)); effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); ins_cost(300); format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %} - ins_encode( enc_Array_Equals(ary1, ary2, tmp1, result)); + ins_encode %{ + __ array_equals(true, $ary1$$Register, $ary2$$Register, + $tmp1$$Register, $tmp2$$Register, + $result$$Register, true /* byte */); + %} + ins_pipe(long_memory_op); +%} + +instruct array_equalsC(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, + o7RegI tmp2, flagsReg ccr) %{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (AryEq ary1 ary2)); + effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); + ins_cost(300); + format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %} + ins_encode %{ + __ array_equals(true, $ary1$$Register, $ary2$$Register, + $tmp1$$Register, $tmp2$$Register, + $result$$Register, false /* byte */); + %} + ins_pipe(long_memory_op); +%} + +// char[] to byte[] compression +instruct string_compress(o0RegP src, o1RegP dst, g3RegI len, notemp_iRegI result, iRegL tmp, flagsReg ccr) %{ + predicate(UseVIS < 3); + match(Set result (StrCompressedCopy src (Binary dst len))); + effect(TEMP result, TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr); + ins_cost(300); + format %{ "String Compress $src,$dst,$len -> $result // KILL $tmp" %} + ins_encode %{ + Label Ldone; + __ signx($len$$Register); + __ cmp_zero_and_br(Assembler::zero, $len$$Register, Ldone, false, Assembler::pn); + __ delayed()->mov($len$$Register, $result$$Register); // copy count + __ string_compress($src$$Register, $dst$$Register, $len$$Register, $result$$Register, $tmp$$Register, Ldone); + __ bind(Ldone); + %} + ins_pipe(long_memory_op); +%} + +// fast char[] to byte[] compression using VIS instructions +instruct string_compress_fast(o0RegP src, o1RegP dst, g3RegI len, notemp_iRegI result, + iRegL tmp1, iRegL tmp2, iRegL tmp3, iRegL tmp4, + regD ftmp1, regD ftmp2, regD ftmp3, flagsReg ccr) %{ + predicate(UseVIS >= 3); + match(Set result (StrCompressedCopy src (Binary dst len))); + effect(TEMP result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ftmp1, TEMP ftmp2, TEMP ftmp3, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr); + ins_cost(300); + format %{ "String Compress Fast $src,$dst,$len -> $result // KILL $tmp1,$tmp2,$tmp3,$tmp4,$ftmp1,$ftmp2,$ftmp3" %} + ins_encode %{ + Label Ldone; + __ signx($len$$Register); + __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, + $ftmp1$$FloatRegister, $ftmp2$$FloatRegister, $ftmp3$$FloatRegister, Ldone); + __ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone); + __ string_compress($src$$Register, $dst$$Register, $len$$Register, $result$$Register, $tmp1$$Register, Ldone); + __ bind(Ldone); + %} + ins_pipe(long_memory_op); +%} + +// byte[] to char[] inflation +instruct string_inflate(Universe dummy, o0RegP src, o1RegP dst, g3RegI len, + iRegL tmp, flagsReg ccr) %{ + match(Set dummy (StrInflatedCopy src (Binary dst len))); + effect(TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr); + ins_cost(300); + format %{ "String Inflate $src,$dst,$len // KILL $tmp" %} + ins_encode %{ + Label Ldone; + __ signx($len$$Register); + __ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone); + __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, Ldone); + __ bind(Ldone); + %} + ins_pipe(long_memory_op); +%} + +// fast byte[] to char[] inflation using VIS instructions +instruct string_inflate_fast(Universe dummy, o0RegP src, o1RegP dst, g3RegI len, + iRegL tmp, regD ftmp1, regD ftmp2, regD ftmp3, regD ftmp4, flagsReg ccr) %{ + predicate(UseVIS >= 3); + match(Set dummy (StrInflatedCopy src (Binary dst len))); + effect(TEMP tmp, TEMP ftmp1, TEMP ftmp2, TEMP ftmp3, TEMP ftmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr); + ins_cost(300); + format %{ "String Inflate Fast $src,$dst,$len // KILL $tmp,$ftmp1,$ftmp2,$ftmp3,$ftmp4" %} + ins_encode %{ + Label Ldone; + __ signx($len$$Register); + __ string_inflate_16($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, + $ftmp1$$FloatRegister, $ftmp2$$FloatRegister, $ftmp3$$FloatRegister, $ftmp4$$FloatRegister, Ldone); + __ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone); + __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, Ldone); + __ bind(Ldone); + %} ins_pipe(long_memory_op); %} diff --git a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp index e0be8b60ff9..24b008b4243 100644 --- a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp @@ -83,7 +83,26 @@ declare_constant(VM_Version::vis1_instructions_m) \ declare_constant(VM_Version::vis2_instructions_m) \ declare_constant(VM_Version::vis3_instructions_m) \ - declare_constant(VM_Version::cbcond_instructions_m) + declare_constant(VM_Version::cbcond_instructions_m) \ + declare_constant(VM_Version::v8_instructions_m) \ + declare_constant(VM_Version::hardware_mul32_m) \ + declare_constant(VM_Version::hardware_div32_m) \ + declare_constant(VM_Version::hardware_fsmuld_m) \ + declare_constant(VM_Version::hardware_popc_m) \ + declare_constant(VM_Version::v9_instructions_m) \ + declare_constant(VM_Version::sun4v_m) \ + declare_constant(VM_Version::blk_init_instructions_m) \ + declare_constant(VM_Version::fmaf_instructions_m) \ + declare_constant(VM_Version::fmau_instructions_m) \ + declare_constant(VM_Version::sparc64_family_m) \ + declare_constant(VM_Version::M_family_m) \ + declare_constant(VM_Version::T_family_m) \ + declare_constant(VM_Version::T1_model_m) \ + declare_constant(VM_Version::sparc5_instructions_m) \ + declare_constant(VM_Version::aes_instructions_m) \ + declare_constant(VM_Version::sha1_instruction_m) \ + declare_constant(VM_Version::sha256_instruction_m) \ + declare_constant(VM_Version::sha512_instruction_m) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 0d11387d411..88db2698cda 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -3036,6 +3036,35 @@ void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) { emit_int8(imm8); } +void Assembler::pcmpeqw(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x75, dst, src, VEX_SIMD_66, + false, (VM_Version::supports_avx512dq() == false)); +} + +void Assembler::vpcmpeqw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "some form of AVX must be enabled"); + emit_vex_arith(0x75, dst, nds, src, VEX_SIMD_66, vector_len, + false, (VM_Version::supports_avx512dq() == false)); +} + +void Assembler::pmovmskb(Register dst, XMMRegister src) { + assert(VM_Version::supports_sse2(), ""); + int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, true, VEX_OPCODE_0F, + false, AVX_128bit, (VM_Version::supports_avx512dq() == false)); + emit_int8((unsigned char)0xD7); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vpmovmskb(Register dst, XMMRegister src) { + assert(VM_Version::supports_avx2(), ""); + int vector_len = AVX_256bit; + int encode = vex_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, + vector_len, VEX_OPCODE_0F, true, false); + emit_int8((unsigned char)0xD7); + emit_int8((unsigned char)(0xC0 | encode)); +} + void Assembler::pextrd(Register dst, XMMRegister src, int imm8) { assert(VM_Version::supports_sse4_1(), ""); int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ true, @@ -3108,6 +3137,17 @@ void Assembler::pmovzxbw(XMMRegister dst, XMMRegister src) { emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::vpmovzxbw(XMMRegister dst, Address src) { + assert(VM_Version::supports_avx(), ""); + InstructionMark im(this); + bool vector256 = true; + assert(dst != xnoreg, "sanity"); + int dst_enc = dst->encoding(); + vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256); + emit_int8(0x30); + emit_operand(dst, src); +} + // generic void Assembler::pop(Register dst) { int encode = prefix_and_encode(dst->encoding()); @@ -5370,6 +5410,16 @@ void Assembler::vpbroadcastd(XMMRegister dst, XMMRegister src) { emit_int8((unsigned char)(0xC0 | encode)); } +// duplicate 2-bytes integer data from src into 16 locations in dest +void Assembler::vpbroadcastw(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_avx2(), ""); + bool vector_len = AVX_256bit; + int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, + vector_len, VEX_OPCODE_0F_38, false); + emit_int8(0x79); + emit_int8((unsigned char)(0xC0 | encode)); +} + // duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL void Assembler::evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len) { _instruction_uses_vl = true; diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index db1afca3d46..28210a7af47 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -1682,6 +1682,12 @@ private: void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); void pcmpestri(XMMRegister xmm1, Address src, int imm8); + void pcmpeqw(XMMRegister dst, XMMRegister src); + void vpcmpeqw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + + void pmovmskb(Register dst, XMMRegister src); + void vpmovmskb(Register dst, XMMRegister src); + // SSE 4.1 extract void pextrd(Register dst, XMMRegister src, int imm8); void pextrq(Register dst, XMMRegister src, int imm8); @@ -1698,6 +1704,8 @@ private: void pmovzxbw(XMMRegister dst, XMMRegister src); void pmovzxbw(XMMRegister dst, Address src); + void vpmovzxbw(XMMRegister dst, Address src); + #ifndef _LP64 // no 32bit push/pop on amd64 void popl(Address dst); #endif @@ -2116,6 +2124,9 @@ private: // duplicate 4-bytes integer data from src into 8 locations in dest void vpbroadcastd(XMMRegister dst, XMMRegister src); + // duplicate 2-bytes integer data from src into 16 locations in dest + void vpbroadcastw(XMMRegister dst, XMMRegister src); + // duplicate n-bytes integer data from src into vector_len locations in dest void evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len); void evpbroadcastb(XMMRegister dst, Address src, int vector_len); diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index f09d6107092..bd7d145e991 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -509,86 +509,6 @@ int LIR_Assembler::emit_deopt_handler() { } -// This is the fast version of java.lang.String.compare; it has not -// OSR-entry and therefore, we generate a slow version for OSR's -void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info) { - __ movptr (rbx, rcx); // receiver is in rcx - __ movptr (rax, arg1->as_register()); - - // Get addresses of first characters from both Strings - __ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes())); - if (java_lang_String::has_offset_field()) { - __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes())); - __ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes())); - __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); - } else { - __ movl (rax, Address(rsi, arrayOopDesc::length_offset_in_bytes())); - __ lea (rsi, Address(rsi, arrayOopDesc::base_offset_in_bytes(T_CHAR))); - } - - // rbx, may be NULL - add_debug_info_for_null_check_here(info); - __ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes())); - if (java_lang_String::has_offset_field()) { - __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes())); - __ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes())); - __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); - } else { - __ movl (rbx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); - __ lea (rdi, Address(rdi, arrayOopDesc::base_offset_in_bytes(T_CHAR))); - } - - // compute minimum length (in rax) and difference of lengths (on top of stack) - __ mov (rcx, rbx); - __ subptr(rbx, rax); // subtract lengths - __ push (rbx); // result - __ cmov (Assembler::lessEqual, rax, rcx); - - // is minimum length 0? - Label noLoop, haveResult; - __ testptr (rax, rax); - __ jcc (Assembler::zero, noLoop); - - // compare first characters - __ load_unsigned_short(rcx, Address(rdi, 0)); - __ load_unsigned_short(rbx, Address(rsi, 0)); - __ subl(rcx, rbx); - __ jcc(Assembler::notZero, haveResult); - // starting loop - __ decrement(rax); // we already tested index: skip one - __ jcc(Assembler::zero, noLoop); - - // set rsi.edi to the end of the arrays (arrays have same length) - // negate the index - - __ lea(rsi, Address(rsi, rax, Address::times_2, type2aelembytes(T_CHAR))); - __ lea(rdi, Address(rdi, rax, Address::times_2, type2aelembytes(T_CHAR))); - __ negptr(rax); - - // compare the strings in a loop - - Label loop; - __ align(wordSize); - __ bind(loop); - __ load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0)); - __ load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0)); - __ subl(rcx, rbx); - __ jcc(Assembler::notZero, haveResult); - __ increment(rax); - __ jcc(Assembler::notZero, loop); - - // strings are equal up to min length - - __ bind(noLoop); - __ pop(rax); - return_op(LIR_OprFact::illegalOpr); - - __ bind(haveResult); - // leave instruction is going to discard the TOS value - __ mov (rax, rcx); // result of call is in rax, -} - - void LIR_Assembler::return_op(LIR_Opr result) { assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == rax, "word returns are in rax,"); if (!result->is_illegal() && result->is_float_kind() && !result->is_xmm_register()) { @@ -1667,8 +1587,8 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L Register Rtmp1 = noreg; // check if it needs to be profiled - ciMethodData* md; - ciProfileData* data; + ciMethodData* md = NULL; + ciProfileData* data = NULL; if (op->should_profile()) { ciMethod* method = op->profiled_method(); @@ -1827,8 +1747,8 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { CodeStub* stub = op->stub(); // check if it needs to be profiled - ciMethodData* md; - ciProfileData* data; + ciMethodData* md = NULL; + ciProfileData* data = NULL; if (op->should_profile()) { ciMethod* method = op->profiled_method(); @@ -2005,7 +1925,8 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L case lir_cond_greater: acond = Assembler::greater; ncond = Assembler::lessEqual; break; case lir_cond_belowEqual: acond = Assembler::belowEqual; ncond = Assembler::above; break; case lir_cond_aboveEqual: acond = Assembler::aboveEqual; ncond = Assembler::below; break; - default: ShouldNotReachHere(); + default: acond = Assembler::equal; ncond = Assembler::notEqual; + ShouldNotReachHere(); } if (opr1->is_cpu_register()) { @@ -3181,27 +3102,23 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point"); int elem_size = type2aelembytes(basic_type); - int shift_amount; Address::ScaleFactor scale; switch (elem_size) { case 1 : - shift_amount = 0; scale = Address::times_1; break; case 2 : - shift_amount = 1; scale = Address::times_2; break; case 4 : - shift_amount = 2; scale = Address::times_4; break; case 8 : - shift_amount = 3; scale = Address::times_8; break; default: + scale = Address::no_scale; ShouldNotReachHere(); } diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index 54ceb34cb72..9933655cdba 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -195,7 +195,7 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o LIR_Opr LIRGenerator::load_immediate(int x, BasicType type) { - LIR_Opr r; + LIR_Opr r = NULL; if (type == T_LONG) { r = LIR_OprFact::longConst(x); } else if (type == T_INT) { @@ -484,7 +484,7 @@ void LIRGenerator::do_ArithmeticOp_Long(ArithmeticOp* x) { __ cmp(lir_cond_equal, right.result(), LIR_OprFact::longConst(0)); __ branch(lir_cond_equal, T_LONG, new DivByZeroStub(info)); - address entry; + address entry = NULL; switch (x->op()) { case Bytecodes::_lrem: entry = CAST_FROM_FN_PTR(address, SharedRuntime::lrem); @@ -1072,7 +1072,7 @@ LIR_Opr fixed_register_for(BasicType type) { void LIRGenerator::do_Convert(Convert* x) { // flags that vary for the different operations and different SSE-settings - bool fixed_input, fixed_result, round_result, needs_stub; + bool fixed_input = false, fixed_result = false, round_result = false, needs_stub = false; switch (x->op()) { case Bytecodes::_i2l: // fall through diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index fe81aac91f4..43c4cca5b2a 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -91,6 +91,8 @@ define_pd_global(size_t, CMSYoungGenPerWorker, 64*M); // default max size of CM define_pd_global(uintx, TypeProfileLevel, 111); +define_pd_global(bool, CompactStrings, true); + define_pd_global(bool, PreserveFramePointer, false); #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ diff --git a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp index e4fb943a925..a45e0eb9aa3 100644 --- a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp @@ -48,7 +48,7 @@ GetDoubleField_t JNI_FastGetField::jni_fast_GetDoubleField_fp; // between loads, which is much more efficient than lfence. address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { - const char *name; + const char *name = NULL; switch (type) { case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break; case T_BYTE: name = "jni_fast_GetByteField"; break; @@ -122,7 +122,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { slowcase_entry_pclist[count++] = __ pc(); __ bind (slow); - address slow_case_addr; + address slow_case_addr = NULL; switch (type) { case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; @@ -256,7 +256,7 @@ address JNI_FastGetField::generate_fast_get_long_field() { } address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { - const char *name; + const char *name = NULL; switch (type) { case T_FLOAT: name = "jni_fast_GetFloatField"; break; case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; @@ -337,7 +337,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { slowcase_entry_pclist[count++] = __ pc(); __ bind (slow); - address slow_case_addr; + address slow_case_addr = NULL; switch (type) { case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break; diff --git a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp index 1f523c7621d..7286fd124b8 100644 --- a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp @@ -51,7 +51,7 @@ static const Register rcounter_addr = r11; // since that may scratch r10! address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { - const char *name; + const char *name = NULL; switch (type) { case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break; case T_BYTE: name = "jni_fast_GetByteField"; break; @@ -111,7 +111,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { slowcase_entry_pclist[count++] = __ pc(); __ bind (slow); - address slow_case_addr; + address slow_case_addr = NULL; switch (type) { case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; @@ -153,7 +153,7 @@ address JNI_FastGetField::generate_fast_get_long_field() { } address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { - const char *name; + const char *name = NULL; switch (type) { case T_FLOAT: name = "jni_fast_GetFloatField"; break; case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; @@ -206,7 +206,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { slowcase_entry_pclist[count++] = __ pc(); __ bind (slow); - address slow_case_addr; + address slow_case_addr = NULL; switch (type) { case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); diff --git a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp index 6b467b1110b..a7d5c62ef38 100644 --- a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp +++ b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp @@ -85,6 +85,23 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) { } } +void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) { + address pc = _instructions->start() + pc_offset; + if (HotSpotMetaspaceConstantImpl::compressed(constant)) { +#ifdef _LP64 + address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand); + *((narrowKlass*) operand) = record_narrow_metadata_reference(constant); + TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); +#else + fatal("compressed Klass* on 32bit"); +#endif + } else { + address operand = Assembler::locate_operand(pc, Assembler::imm_operand); + *((Metadata**) operand) = record_metadata_reference(constant); + TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); + } +} + void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) { address pc = _instructions->start() + pc_offset; @@ -100,16 +117,6 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset); } -void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { - if (cb->is_nmethod()) { - nmethod* nm = (nmethod*) cb; - nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point()); - } else { - nativeJump_at((address)inst)->set_jump_destination(cb->code_begin()); - } - _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); -} - void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { address pc = (address) inst; if (inst->is_call()) { diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index eef3cd90afe..100ea5962c6 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -46,6 +46,9 @@ #include "gc/g1/heapRegion.hpp" #endif // INCLUDE_ALL_GCS #include "crc32c.h" +#ifdef COMPILER2 +#include "opto/intrinsicnode.hpp" +#endif #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -6299,25 +6302,34 @@ void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp) { } } +#ifdef COMPILER2 + // IndexOf for constant substrings with size >= 8 chars // which don't need to be loaded through stack. void MacroAssembler::string_indexofC8(Register str1, Register str2, Register cnt1, Register cnt2, int int_cnt2, Register result, - XMMRegister vec, Register tmp) { + XMMRegister vec, Register tmp, + int ae) { ShortBranchVerifier sbv(this); assert(UseSSE42Intrinsics, "SSE4.2 is required"); + assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); - // This method uses pcmpestri instruction with bound registers + // This method uses the pcmpestri instruction with bound registers // inputs: // xmm - substring // rax - substring length (elements count) // mem - scanned string // rdx - string length (elements count) // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // 0xc - mode: 1100 (substring search) + 00 (unsigned bytes) // outputs: // rcx - matched index in string assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); + int mode = (ae == StrIntrinsicNode::LL) ? 0x0c : 0x0d; // bytes or shorts + int stride = (ae == StrIntrinsicNode::LL) ? 16 : 8; //UU, UL -> 8 + Address::ScaleFactor scale1 = (ae == StrIntrinsicNode::LL) ? Address::times_1 : Address::times_2; + Address::ScaleFactor scale2 = (ae == StrIntrinsicNode::UL) ? Address::times_1 : scale1; Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR, @@ -6326,20 +6338,28 @@ void MacroAssembler::string_indexofC8(Register str1, Register str2, // Note, inline_string_indexOf() generates checks: // if (substr.count > string.count) return -1; // if (substr.count == 0) return 0; - assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars"); + assert(int_cnt2 >= stride, "this code is used only for cnt2 >= 8 chars"); // Load substring. - movdqu(vec, Address(str2, 0)); + if (ae == StrIntrinsicNode::UL) { + pmovzxbw(vec, Address(str2, 0)); + } else { + movdqu(vec, Address(str2, 0)); + } movl(cnt2, int_cnt2); movptr(result, str1); // string addr - if (int_cnt2 > 8) { + if (int_cnt2 > stride) { jmpb(SCAN_TO_SUBSTR); // Reload substr for rescan, this code // is executed only for large substrings (> 8 chars) bind(RELOAD_SUBSTR); - movdqu(vec, Address(str2, 0)); + if (ae == StrIntrinsicNode::UL) { + pmovzxbw(vec, Address(str2, 0)); + } else { + movdqu(vec, Address(str2, 0)); + } negptr(cnt2); // Jumped here with negative cnt2, convert to positive bind(RELOAD_STR); @@ -6358,15 +6378,15 @@ void MacroAssembler::string_indexofC8(Register str1, Register str2, cmpl(cnt1, cnt2); jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring - addptr(result, 2); + addptr(result, (1< 8) // Scan string for start of substr in 16-byte vectors bind(SCAN_TO_SUBSTR); - pcmpestri(vec, Address(result, 0), 0x0d); + pcmpestri(vec, Address(result, 0), mode); jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1 - subl(cnt1, 8); + subl(cnt1, stride); jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string cmpl(cnt1, cnt2); jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring @@ -6376,19 +6396,19 @@ void MacroAssembler::string_indexofC8(Register str1, Register str2, // Found a potential substr bind(FOUND_CANDIDATE); // Matched whole vector if first element matched (tmp(rcx) == 0). - if (int_cnt2 == 8) { + if (int_cnt2 == stride) { jccb(Assembler::overflow, RET_FOUND); // OF == 1 } else { // int_cnt2 > 8 jccb(Assembler::overflow, FOUND_SUBSTR); } // After pcmpestri tmp(rcx) contains matched element index // Compute start addr of substr - lea(result, Address(result, tmp, Address::times_2)); + lea(result, Address(result, tmp, scale1)); // Make sure string is still long enough subl(cnt1, tmp); cmpl(cnt1, cnt2); - if (int_cnt2 == 8) { + if (int_cnt2 == stride) { jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); } else { // int_cnt2 > 8 jccb(Assembler::greaterEqual, MATCH_SUBSTR_HEAD); @@ -6399,11 +6419,11 @@ void MacroAssembler::string_indexofC8(Register str1, Register str2, movl(result, -1); jmpb(EXIT); - if (int_cnt2 > 8) { + if (int_cnt2 > stride) { // This code is optimized for the case when whole substring // is matched if its head is matched. bind(MATCH_SUBSTR_HEAD); - pcmpestri(vec, Address(result, 0), 0x0d); + pcmpestri(vec, Address(result, 0), mode); // Reload only string if does not match jccb(Assembler::noOverflow, RELOAD_STR); // OF == 0 @@ -6412,31 +6432,41 @@ void MacroAssembler::string_indexofC8(Register str1, Register str2, bind(FOUND_SUBSTR); // First 8 chars are already matched. negptr(cnt2); - addptr(cnt2, 8); + addptr(cnt2, stride); bind(SCAN_SUBSTR); - subl(cnt1, 8); - cmpl(cnt2, -8); // Do not read beyond substring + subl(cnt1, stride); + cmpl(cnt2, -stride); // Do not read beyond substring jccb(Assembler::lessEqual, CONT_SCAN_SUBSTR); // Back-up strings to avoid reading beyond substring: // cnt1 = cnt1 - cnt2 + 8 addl(cnt1, cnt2); // cnt2 is negative - addl(cnt1, 8); - movl(cnt2, 8); negptr(cnt2); + addl(cnt1, stride); + movl(cnt2, stride); negptr(cnt2); bind(CONT_SCAN_SUBSTR); if (int_cnt2 < (int)G) { - movdqu(vec, Address(str2, cnt2, Address::times_2, int_cnt2*2)); - pcmpestri(vec, Address(result, cnt2, Address::times_2, int_cnt2*2), 0x0d); + int tail_off1 = int_cnt2< string.count) return -1; // if (substr.count == 0) return 0; // - assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0"); - - // This method uses pcmpestri instruction with bound registers + int stride = (ae == StrIntrinsicNode::LL) ? 16 : 8; //UU, UL -> 8 + assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < stride), "should be != 0"); + // This method uses the pcmpestri instruction with bound registers // inputs: // xmm - substring // rax - substring length (elements count) // mem - scanned string // rdx - string length (elements count) // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // 0xc - mode: 1100 (substring search) + 00 (unsigned bytes) // outputs: // rcx - matched index in string assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); + int mode = (ae == StrIntrinsicNode::LL) ? 0x0c : 0x0d; // bytes or shorts + Address::ScaleFactor scale1 = (ae == StrIntrinsicNode::LL) ? Address::times_1 : Address::times_2; + Address::ScaleFactor scale2 = (ae == StrIntrinsicNode::UL) ? Address::times_1 : scale1; Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR, RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR, @@ -6492,23 +6531,40 @@ void MacroAssembler::string_indexof(Register str1, Register str2, movptr(tmp, rsp); // save old SP if (int_cnt2 > 0) { // small (< 8 chars) constant substring - if (int_cnt2 == 1) { // One char + if (int_cnt2 == (1>>scale2)) { // One byte + assert((ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL), "Only possible for latin1 encoding"); + load_unsigned_byte(result, Address(str2, 0)); + movdl(vec, result); // move 32 bits + } else if (ae == StrIntrinsicNode::LL && int_cnt2 == 3) { // Three bytes + // Not enough header space in 32-bit VM: 12+3 = 15. + movl(result, Address(str2, -1)); + shrl(result, 8); + movdl(vec, result); // move 32 bits + } else if (ae != StrIntrinsicNode::UL && int_cnt2 == (2>>scale2)) { // One char load_unsigned_short(result, Address(str2, 0)); movdl(vec, result); // move 32 bits - } else if (int_cnt2 == 2) { // Two chars + } else if (ae != StrIntrinsicNode::UL && int_cnt2 == (4>>scale2)) { // Two chars movdl(vec, Address(str2, 0)); // move 32 bits - } else if (int_cnt2 == 4) { // Four chars + } else if (ae != StrIntrinsicNode::UL && int_cnt2 == (8>>scale2)) { // Four chars movq(vec, Address(str2, 0)); // move 64 bits - } else { // cnt2 = { 3, 5, 6, 7 } + } else { // cnt2 = { 3, 5, 6, 7 } || (ae == StrIntrinsicNode::UL && cnt2 ={2, ..., 7}) // Array header size is 12 bytes in 32-bit VM // + 6 bytes for 3 chars == 18 bytes, // enough space to load vec and shift. assert(HeapWordSize*TypeArrayKlass::header_size() >= 12,"sanity"); - movdqu(vec, Address(str2, (int_cnt2*2)-16)); - psrldq(vec, 16-(int_cnt2*2)); + if (ae == StrIntrinsicNode::UL) { + int tail_off = int_cnt2-8; + pmovzxbw(vec, Address(str2, tail_off)); + psrldq(vec, -2*tail_off); + } + else { + int tail_off = int_cnt2*(1< 0) { // Constant substring // Repeat search for small substring (< 8 chars) // from new point without reloading substring. // Have to check that we don't read beyond string. - cmpl(tmp, 8-int_cnt2); + cmpl(tmp, stride-int_cnt2); jccb(Assembler::greater, ADJUST_STR); // Fall through if matched whole substring. } else { // non constant @@ -6660,12 +6735,12 @@ void MacroAssembler::string_indexof(Register str1, Register str2, addl(tmp, cnt2); // Found result if we matched whole substring. - cmpl(tmp, 8); + cmpl(tmp, stride); jccb(Assembler::lessEqual, RET_FOUND); // Repeat search for small substring (<= 8 chars) // from new point 'str1' without reloading substring. - cmpl(cnt2, 8); + cmpl(cnt2, stride); // Have to check that we don't read beyond string. jccb(Assembler::lessEqual, ADJUST_STR); @@ -6678,26 +6753,40 @@ void MacroAssembler::string_indexof(Register str1, Register str2, jccb(Assembler::equal, CHECK_NEXT); bind(SCAN_SUBSTR); - pcmpestri(vec, Address(str1, 0), 0x0d); + pcmpestri(vec, Address(str1, 0), mode); // Need to reload strings pointers if not matched whole vector jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 bind(CHECK_NEXT); - subl(cnt2, 8); + subl(cnt2, stride); jccb(Assembler::lessEqual, RET_FOUND_LONG); // Found full substring addptr(str1, 16); - addptr(str2, 16); - subl(cnt1, 8); - cmpl(cnt2, 8); // Do not read beyond substring + if (ae == StrIntrinsicNode::UL) { + addptr(str2, 8); + } else { + addptr(str2, 16); + } + subl(cnt1, stride); + cmpl(cnt2, stride); // Do not read beyond substring jccb(Assembler::greaterEqual, CONT_SCAN_SUBSTR); // Back-up strings to avoid reading beyond substring. - lea(str2, Address(str2, cnt2, Address::times_2, -16)); - lea(str1, Address(str1, cnt2, Address::times_2, -16)); + + if (ae == StrIntrinsicNode::UL) { + lea(str2, Address(str2, cnt2, scale2, -8)); + lea(str1, Address(str1, cnt2, scale1, -16)); + } else { + lea(str2, Address(str2, cnt2, scale2, -16)); + lea(str1, Address(str1, cnt2, scale1, -16)); + } subl(cnt1, cnt2); - movl(cnt2, 8); - addl(cnt1, 8); + movl(cnt2, stride); + addl(cnt1, stride); bind(CONT_SCAN_SUBSTR); - movdqu(vec, Address(str2, 0)); + if (ae == StrIntrinsicNode::UL) { + pmovzxbw(vec, Address(str2, 0)); + } else { + movdqu(vec, Address(str2, 0)); + } jmpb(SCAN_SUBSTR); bind(RET_FOUND_LONG); @@ -6707,20 +6796,143 @@ void MacroAssembler::string_indexof(Register str1, Register str2, bind(RET_FOUND); // Compute substr offset subptr(result, str1); - shrl(result, 1); // index - + if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) { + shrl(result, 1); // index + } bind(CLEANUP); pop(rsp); // restore SP } // string_indexof -// Compare strings. +void MacroAssembler::string_indexof_char(Register str1, Register cnt1, Register ch, Register result, + XMMRegister vec1, XMMRegister vec2, XMMRegister vec3, Register tmp) { + ShortBranchVerifier sbv(this); + assert(UseSSE42Intrinsics, "SSE4.2 is required"); + + int stride = 8; + + Label FOUND_CHAR, SCAN_TO_CHAR, SCAN_TO_CHAR_LOOP, + SCAN_TO_8_CHAR, SCAN_TO_8_CHAR_LOOP, SCAN_TO_16_CHAR_LOOP, + RET_NOT_FOUND, SCAN_TO_8_CHAR_INIT, + FOUND_SEQ_CHAR, DONE_LABEL; + + movptr(result, str1); + if (UseAVX >= 2) { + cmpl(cnt1, stride); + jccb(Assembler::less, SCAN_TO_CHAR_LOOP); + cmpl(cnt1, 2*stride); + jccb(Assembler::less, SCAN_TO_8_CHAR_INIT); + movdl(vec1, ch); + vpbroadcastw(vec1, vec1); + vpxor(vec2, vec2); + movl(tmp, cnt1); + andl(tmp, 0xFFFFFFF0); //vector count (in chars) + andl(cnt1,0x0000000F); //tail count (in chars) + + bind(SCAN_TO_16_CHAR_LOOP); + vmovdqu(vec3, Address(result, 0)); + vpcmpeqw(vec3, vec3, vec1, true); + vptest(vec2, vec3); + jcc(Assembler::carryClear, FOUND_CHAR); + addptr(result, 32); + subl(tmp, 2*stride); + jccb(Assembler::notZero, SCAN_TO_16_CHAR_LOOP); + jmp(SCAN_TO_8_CHAR); + bind(SCAN_TO_8_CHAR_INIT); + movdl(vec1, ch); + pshuflw(vec1, vec1, 0x00); + pshufd(vec1, vec1, 0); + pxor(vec2, vec2); + } + if (UseAVX >= 2 || UseSSE42Intrinsics) { + bind(SCAN_TO_8_CHAR); + cmpl(cnt1, stride); + if (UseAVX >= 2) { + jccb(Assembler::less, SCAN_TO_CHAR); + } + if (!(UseAVX >= 2)) { + jccb(Assembler::less, SCAN_TO_CHAR_LOOP); + movdl(vec1, ch); + pshuflw(vec1, vec1, 0x00); + pshufd(vec1, vec1, 0); + pxor(vec2, vec2); + } + movl(tmp, cnt1); + andl(tmp, 0xFFFFFFF8); //vector count (in chars) + andl(cnt1,0x00000007); //tail count (in chars) + + bind(SCAN_TO_8_CHAR_LOOP); + movdqu(vec3, Address(result, 0)); + pcmpeqw(vec3, vec1); + ptest(vec2, vec3); + jcc(Assembler::carryClear, FOUND_CHAR); + addptr(result, 16); + subl(tmp, stride); + jccb(Assembler::notZero, SCAN_TO_8_CHAR_LOOP); + } + bind(SCAN_TO_CHAR); + testl(cnt1, cnt1); + jcc(Assembler::zero, RET_NOT_FOUND); + + bind(SCAN_TO_CHAR_LOOP); + load_unsigned_short(tmp, Address(result, 0)); + cmpl(ch, tmp); + jccb(Assembler::equal, FOUND_SEQ_CHAR); + addptr(result, 2); + subl(cnt1, 1); + jccb(Assembler::zero, RET_NOT_FOUND); + jmp(SCAN_TO_CHAR_LOOP); + + bind(RET_NOT_FOUND); + movl(result, -1); + jmpb(DONE_LABEL); + + if (UseAVX >= 2 || UseSSE42Intrinsics) { + bind(FOUND_CHAR); + if (UseAVX >= 2) { + vpmovmskb(tmp, vec3); + } else { + pmovmskb(tmp, vec3); + } + bsfl(ch, tmp); + addl(result, ch); + } + + bind(FOUND_SEQ_CHAR); + subptr(result, str1); + shrl(result, 1); + + bind(DONE_LABEL); +} // string_indexof_char + +// helper function for string_compare +void MacroAssembler::load_next_elements(Register elem1, Register elem2, Register str1, Register str2, + Address::ScaleFactor scale, Address::ScaleFactor scale1, + Address::ScaleFactor scale2, Register index, int ae) { + if (ae == StrIntrinsicNode::LL) { + load_unsigned_byte(elem1, Address(str1, index, scale, 0)); + load_unsigned_byte(elem2, Address(str2, index, scale, 0)); + } else if (ae == StrIntrinsicNode::UU) { + load_unsigned_short(elem1, Address(str1, index, scale, 0)); + load_unsigned_short(elem2, Address(str2, index, scale, 0)); + } else { + load_unsigned_byte(elem1, Address(str1, index, scale1, 0)); + load_unsigned_short(elem2, Address(str2, index, scale2, 0)); + } +} + +// Compare strings, used for char[] and byte[]. void MacroAssembler::string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register result, - XMMRegister vec1) { + XMMRegister vec1, int ae) { ShortBranchVerifier sbv(this); Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL; + int stride, stride2, adr_stride, adr_stride1, adr_stride2; + Address::ScaleFactor scale, scale1, scale2; + if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) { + shrl(cnt2, 1); + } // Compute the minimum of the string lengths and the // difference of the string lengths (stack). // Do the conditional move stuff @@ -6732,32 +6944,68 @@ void MacroAssembler::string_compare(Register str1, Register str2, // Is the minimum length zero? testl(cnt2, cnt2); jcc(Assembler::zero, LENGTH_DIFF_LABEL); - - // Compare first characters - load_unsigned_short(result, Address(str1, 0)); - load_unsigned_short(cnt1, Address(str2, 0)); + if (ae == StrIntrinsicNode::LL) { + // Load first bytes + load_unsigned_byte(result, Address(str1, 0)); + load_unsigned_byte(cnt1, Address(str2, 0)); + } else if (ae == StrIntrinsicNode::UU) { + // Load first characters + load_unsigned_short(result, Address(str1, 0)); + load_unsigned_short(cnt1, Address(str2, 0)); + } else { + load_unsigned_byte(result, Address(str1, 0)); + load_unsigned_short(cnt1, Address(str2, 0)); + } subl(result, cnt1); jcc(Assembler::notZero, POP_LABEL); + + if (ae == StrIntrinsicNode::UU) { + // Divide length by 2 to get number of chars + shrl(cnt2, 1); + } cmpl(cnt2, 1); jcc(Assembler::equal, LENGTH_DIFF_LABEL); - // Check if the strings start at the same location. - cmpptr(str1, str2); - jcc(Assembler::equal, LENGTH_DIFF_LABEL); - - Address::ScaleFactor scale = Address::times_2; - int stride = 8; + // Check if the strings start at the same location and setup scale and stride + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + cmpptr(str1, str2); + jcc(Assembler::equal, LENGTH_DIFF_LABEL); + if (ae == StrIntrinsicNode::LL) { + scale = Address::times_1; + stride = 16; + } else { + scale = Address::times_2; + stride = 8; + } + } else { + scale = Address::no_scale; // not used + scale1 = Address::times_1; + scale2 = Address::times_2; + stride = 8; + } if (UseAVX >= 2 && UseSSE42Intrinsics) { Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR; Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR; Label COMPARE_TAIL_LONG; int pcmpmask = 0x19; + if (ae == StrIntrinsicNode::LL) { + pcmpmask &= ~0x01; + } // Setup to compare 16-chars (32-bytes) vectors, // start from first character again because it has aligned address. - int stride2 = 16; - int adr_stride = stride << scale; + if (ae == StrIntrinsicNode::LL) { + stride2 = 32; + } else { + stride2 = 16; + } + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + adr_stride = stride << scale; + } else { + adr_stride1 = 8; //stride << scale1; + adr_stride2 = 16; //stride << scale2; + } assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri"); // rax and rdx are used by pcmpestri as elements counters @@ -6767,26 +7015,39 @@ void MacroAssembler::string_compare(Register str1, Register str2, // fast path : compare first 2 8-char vectors. bind(COMPARE_16_CHARS); - movdqu(vec1, Address(str1, 0)); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + movdqu(vec1, Address(str1, 0)); + } else { + pmovzxbw(vec1, Address(str1, 0)); + } pcmpestri(vec1, Address(str2, 0), pcmpmask); jccb(Assembler::below, COMPARE_INDEX_CHAR); - movdqu(vec1, Address(str1, adr_stride)); - pcmpestri(vec1, Address(str2, adr_stride), pcmpmask); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + movdqu(vec1, Address(str1, adr_stride)); + pcmpestri(vec1, Address(str2, adr_stride), pcmpmask); + } else { + pmovzxbw(vec1, Address(str1, adr_stride1)); + pcmpestri(vec1, Address(str2, adr_stride2), pcmpmask); + } jccb(Assembler::aboveEqual, COMPARE_WIDE_VECTORS); addl(cnt1, stride); // Compare the characters at index in cnt1 - bind(COMPARE_INDEX_CHAR); //cnt1 has the offset of the mismatching character - load_unsigned_short(result, Address(str1, cnt1, scale)); - load_unsigned_short(cnt2, Address(str2, cnt1, scale)); + bind(COMPARE_INDEX_CHAR); // cnt1 has the offset of the mismatching character + load_next_elements(result, cnt2, str1, str2, scale, scale1, scale2, cnt1, ae); subl(result, cnt2); jmp(POP_LABEL); // Setup the registers to start vector comparison loop bind(COMPARE_WIDE_VECTORS); - lea(str1, Address(str1, result, scale)); - lea(str2, Address(str2, result, scale)); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + lea(str1, Address(str1, result, scale)); + lea(str2, Address(str2, result, scale)); + } else { + lea(str1, Address(str1, result, scale1)); + lea(str2, Address(str2, result, scale2)); + } subl(result, stride2); subl(cnt2, stride2); jccb(Assembler::zero, COMPARE_WIDE_TAIL); @@ -6794,8 +7055,13 @@ void MacroAssembler::string_compare(Register str1, Register str2, // In a loop, compare 16-chars (32-bytes) at once using (vpxor+vptest) bind(COMPARE_WIDE_VECTORS_LOOP); - vmovdqu(vec1, Address(str1, result, scale)); - vpxor(vec1, Address(str2, result, scale)); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + vmovdqu(vec1, Address(str1, result, scale)); + vpxor(vec1, Address(str2, result, scale)); + } else { + vpmovzxbw(vec1, Address(str1, result, scale1)); + vpxor(vec1, Address(str2, result, scale2)); + } vptest(vec1, vec1); jccb(Assembler::notZero, VECTOR_NOT_EQUAL); addptr(result, stride2); @@ -6818,8 +7084,13 @@ void MacroAssembler::string_compare(Register str1, Register str2, bind(VECTOR_NOT_EQUAL); // clean upper bits of YMM registers vpxor(vec1, vec1); - lea(str1, Address(str1, result, scale)); - lea(str2, Address(str2, result, scale)); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + lea(str1, Address(str1, result, scale)); + lea(str2, Address(str2, result, scale)); + } else { + lea(str1, Address(str1, result, scale1)); + lea(str2, Address(str2, result, scale2)); + } jmp(COMPARE_16_CHARS); // Compare tail chars, length between 1 to 15 chars @@ -6828,13 +7099,22 @@ void MacroAssembler::string_compare(Register str1, Register str2, cmpl(cnt2, stride); jccb(Assembler::less, COMPARE_SMALL_STR); - movdqu(vec1, Address(str1, 0)); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + movdqu(vec1, Address(str1, 0)); + } else { + pmovzxbw(vec1, Address(str1, 0)); + } pcmpestri(vec1, Address(str2, 0), pcmpmask); jcc(Assembler::below, COMPARE_INDEX_CHAR); subptr(cnt2, stride); jccb(Assembler::zero, LENGTH_DIFF_LABEL); - lea(str1, Address(str1, result, scale)); - lea(str2, Address(str2, result, scale)); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + lea(str1, Address(str1, result, scale)); + lea(str2, Address(str2, result, scale)); + } else { + lea(str1, Address(str1, result, scale1)); + lea(str2, Address(str2, result, scale2)); + } negptr(cnt2); jmpb(WHILE_HEAD_LABEL); @@ -6846,10 +7126,17 @@ void MacroAssembler::string_compare(Register str1, Register str2, // start from first character again because it has aligned address. movl(result, cnt2); andl(cnt2, ~(stride - 1)); // cnt2 holds the vector count + if (ae == StrIntrinsicNode::LL) { + pcmpmask &= ~0x01; + } jccb(Assembler::zero, COMPARE_TAIL); - - lea(str1, Address(str1, result, scale)); - lea(str2, Address(str2, result, scale)); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + lea(str1, Address(str1, result, scale)); + lea(str2, Address(str2, result, scale)); + } else { + lea(str1, Address(str1, result, scale1)); + lea(str2, Address(str2, result, scale2)); + } negptr(result); // pcmpestri @@ -6865,8 +7152,13 @@ void MacroAssembler::string_compare(Register str1, Register str2, assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri"); bind(COMPARE_WIDE_VECTORS); - movdqu(vec1, Address(str1, result, scale)); - pcmpestri(vec1, Address(str2, result, scale), pcmpmask); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + movdqu(vec1, Address(str1, result, scale)); + pcmpestri(vec1, Address(str2, result, scale), pcmpmask); + } else { + pmovzxbw(vec1, Address(str1, result, scale1)); + pcmpestri(vec1, Address(str2, result, scale2), pcmpmask); + } // After pcmpestri cnt1(rcx) contains mismatched element index jccb(Assembler::below, VECTOR_NOT_EQUAL); // CF==1 @@ -6881,15 +7173,19 @@ void MacroAssembler::string_compare(Register str1, Register str2, movl(cnt2, stride); movl(result, stride); negptr(result); - movdqu(vec1, Address(str1, result, scale)); - pcmpestri(vec1, Address(str2, result, scale), pcmpmask); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + movdqu(vec1, Address(str1, result, scale)); + pcmpestri(vec1, Address(str2, result, scale), pcmpmask); + } else { + pmovzxbw(vec1, Address(str1, result, scale1)); + pcmpestri(vec1, Address(str2, result, scale2), pcmpmask); + } jccb(Assembler::aboveEqual, LENGTH_DIFF_LABEL); // Mismatched characters in the vectors bind(VECTOR_NOT_EQUAL); addptr(cnt1, result); - load_unsigned_short(result, Address(str1, cnt1, scale)); - load_unsigned_short(cnt2, Address(str2, cnt1, scale)); + load_next_elements(result, cnt2, str1, str2, scale, scale1, scale2, cnt1, ae); subl(result, cnt2); jmpb(POP_LABEL); @@ -6898,15 +7194,19 @@ void MacroAssembler::string_compare(Register str1, Register str2, // Fallthru to tail compare } // Shift str2 and str1 to the end of the arrays, negate min - lea(str1, Address(str1, cnt2, scale)); - lea(str2, Address(str2, cnt2, scale)); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + lea(str1, Address(str1, cnt2, scale)); + lea(str2, Address(str2, cnt2, scale)); + } else { + lea(str1, Address(str1, cnt2, scale1)); + lea(str2, Address(str2, cnt2, scale2)); + } decrementl(cnt2); // first character was compared already negptr(cnt2); // Compare the rest of the elements bind(WHILE_HEAD_LABEL); - load_unsigned_short(result, Address(str1, cnt2, scale, 0)); - load_unsigned_short(cnt1, Address(str2, cnt2, scale, 0)); + load_next_elements(result, cnt1, str1, str2, scale, scale1, scale2, cnt2, ae); subl(result, cnt1); jccb(Assembler::notZero, POP_LABEL); increment(cnt2); @@ -6915,6 +7215,10 @@ void MacroAssembler::string_compare(Register str1, Register str2, // Strings are equal up to min length. Return the length difference. bind(LENGTH_DIFF_LABEL); pop(result); + if (ae == StrIntrinsicNode::UU) { + // Divide diff by 2 to get number of chars + sarl(result, 1); + } jmpb(DONE_LABEL); // Discard the stored length difference @@ -6923,23 +7227,164 @@ void MacroAssembler::string_compare(Register str1, Register str2, // That's it bind(DONE_LABEL); + if(ae == StrIntrinsicNode::UL) { + negl(result); + } } -// Compare char[] arrays aligned to 4 bytes or substrings. -void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, - Register limit, Register result, Register chr, - XMMRegister vec1, XMMRegister vec2) { +// Search for Non-ASCII character (Negative byte value) in a byte array, +// return true if it has any and false otherwise. +void MacroAssembler::has_negatives(Register ary1, Register len, + Register result, Register tmp1, + XMMRegister vec1, XMMRegister vec2) { + + // rsi: byte array + // rcx: len + // rax: result ShortBranchVerifier sbv(this); - Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; + assert_different_registers(ary1, len, result, tmp1); + assert_different_registers(vec1, vec2); + Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_CHAR, COMPARE_VECTORS, COMPARE_BYTE; + + // len == 0 + testl(len, len); + jcc(Assembler::zero, FALSE_LABEL); + + movl(result, len); // copy + + if (UseAVX >= 2) { + // With AVX2, use 32-byte vector compare + Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; + + // Compare 32-byte vectors + andl(result, 0x0000001f); // tail count (in bytes) + andl(len, 0xffffffe0); // vector count (in bytes) + jccb(Assembler::zero, COMPARE_TAIL); + + lea(ary1, Address(ary1, len, Address::times_1)); + negptr(len); + + movl(tmp1, 0x80808080); // create mask to test for Unicode chars in vector + movdl(vec2, tmp1); + vpbroadcastd(vec2, vec2); + + bind(COMPARE_WIDE_VECTORS); + vmovdqu(vec1, Address(ary1, len, Address::times_1)); + vptest(vec1, vec2); + jccb(Assembler::notZero, TRUE_LABEL); + addptr(len, 32); + jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); + + testl(result, result); + jccb(Assembler::zero, FALSE_LABEL); + + vmovdqu(vec1, Address(ary1, result, Address::times_1, -32)); + vptest(vec1, vec2); + jccb(Assembler::notZero, TRUE_LABEL); + jmpb(FALSE_LABEL); + + bind(COMPARE_TAIL); // len is zero + movl(len, result); + // Fallthru to tail compare + } else if (UseSSE42Intrinsics) { + // With SSE4.2, use double quad vector compare + Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; + + // Compare 16-byte vectors + andl(result, 0x0000000f); // tail count (in bytes) + andl(len, 0xfffffff0); // vector count (in bytes) + jccb(Assembler::zero, COMPARE_TAIL); + + lea(ary1, Address(ary1, len, Address::times_1)); + negptr(len); + + movl(tmp1, 0x80808080); + movdl(vec2, tmp1); + pshufd(vec2, vec2, 0); + + bind(COMPARE_WIDE_VECTORS); + movdqu(vec1, Address(ary1, len, Address::times_1)); + ptest(vec1, vec2); + jccb(Assembler::notZero, TRUE_LABEL); + addptr(len, 16); + jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); + + testl(result, result); + jccb(Assembler::zero, FALSE_LABEL); + + movdqu(vec1, Address(ary1, result, Address::times_1, -16)); + ptest(vec1, vec2); + jccb(Assembler::notZero, TRUE_LABEL); + jmpb(FALSE_LABEL); + + bind(COMPARE_TAIL); // len is zero + movl(len, result); + // Fallthru to tail compare + } + + // Compare 4-byte vectors + andl(len, 0xfffffffc); // vector count (in bytes) + jccb(Assembler::zero, COMPARE_CHAR); + + lea(ary1, Address(ary1, len, Address::times_1)); + negptr(len); + + bind(COMPARE_VECTORS); + movl(tmp1, Address(ary1, len, Address::times_1)); + andl(tmp1, 0x80808080); + jccb(Assembler::notZero, TRUE_LABEL); + addptr(len, 4); + jcc(Assembler::notZero, COMPARE_VECTORS); + + // Compare trailing char (final 2 bytes), if any + bind(COMPARE_CHAR); + testl(result, 0x2); // tail char + jccb(Assembler::zero, COMPARE_BYTE); + load_unsigned_short(tmp1, Address(ary1, 0)); + andl(tmp1, 0x00008080); + jccb(Assembler::notZero, TRUE_LABEL); + subptr(result, 2); + lea(ary1, Address(ary1, 2)); + + bind(COMPARE_BYTE); + testl(result, 0x1); // tail byte + jccb(Assembler::zero, FALSE_LABEL); + load_unsigned_byte(tmp1, Address(ary1, 0)); + andl(tmp1, 0x00000080); + jccb(Assembler::notEqual, TRUE_LABEL); + jmpb(FALSE_LABEL); + + bind(TRUE_LABEL); + movl(result, 1); // return true + jmpb(DONE); + + bind(FALSE_LABEL); + xorl(result, result); // return false + + // That's it + bind(DONE); + if (UseAVX >= 2) { + // clean upper bits of YMM registers + vpxor(vec1, vec1); + vpxor(vec2, vec2); + } +} + +// Compare char[] or byte[] arrays aligned to 4 bytes or substrings. +void MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register ary2, + Register limit, Register result, Register chr, + XMMRegister vec1, XMMRegister vec2, bool is_char) { + ShortBranchVerifier sbv(this); + Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR, COMPARE_BYTE; int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); - - // Check the input args - cmpptr(ary1, ary2); - jcc(Assembler::equal, TRUE_LABEL); + int base_offset = arrayOopDesc::base_offset_in_bytes(is_char ? T_CHAR : T_BYTE); if (is_array_equ) { + // Check the input args + cmpptr(ary1, ary2); + jcc(Assembler::equal, TRUE_LABEL); + // Need additional checks for arrays_equals. testptr(ary1, ary1); jcc(Assembler::zero, FALSE_LABEL); @@ -6962,7 +7407,10 @@ void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Regist lea(ary2, Address(ary2, base_offset)); } - shll(limit, 1); // byte count != 0 + if (is_array_equ && is_char) { + // arrays_equals when used for char[]. + shll(limit, 1); // byte count != 0 + } movl(result, limit); // copy if (UseAVX >= 2) { @@ -6970,7 +7418,7 @@ void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Regist Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; // Compare 32-byte vectors - andl(result, 0x0000001e); // tail count (in bytes) + andl(result, 0x0000001f); // tail count (in bytes) andl(limit, 0xffffffe0); // vector count (in bytes) jccb(Assembler::zero, COMPARE_TAIL); @@ -7007,7 +7455,7 @@ void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Regist Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; // Compare 16-byte vectors - andl(result, 0x0000000e); // tail count (in bytes) + andl(result, 0x0000000f); // tail count (in bytes) andl(limit, 0xfffffff0); // vector count (in bytes) jccb(Assembler::zero, COMPARE_TAIL); @@ -7059,12 +7507,26 @@ void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Regist // Compare trailing char (final 2 bytes), if any bind(COMPARE_CHAR); testl(result, 0x2); // tail char - jccb(Assembler::zero, TRUE_LABEL); + jccb(Assembler::zero, COMPARE_BYTE); load_unsigned_short(chr, Address(ary1, 0)); load_unsigned_short(limit, Address(ary2, 0)); cmpl(chr, limit); jccb(Assembler::notEqual, FALSE_LABEL); + if (is_array_equ && is_char) { + bind(COMPARE_BYTE); + } else { + lea(ary1, Address(ary1, 2)); + lea(ary2, Address(ary2, 2)); + + bind(COMPARE_BYTE); + testl(result, 0x1); // tail byte + jccb(Assembler::zero, TRUE_LABEL); + load_unsigned_byte(chr, Address(ary1, 0)); + load_unsigned_byte(limit, Address(ary2, 0)); + cmpl(chr, limit); + jccb(Assembler::notEqual, FALSE_LABEL); + } bind(TRUE_LABEL); movl(result, 1); // return true jmpb(DONE); @@ -7081,6 +7543,8 @@ void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Regist } } +#endif + void MacroAssembler::generate_fill(BasicType t, bool aligned, Register to, Register value, Register count, Register rtmp, XMMRegister xtmp) { @@ -9085,6 +9549,179 @@ void MacroAssembler::crc32c_ipl_alg2_alt2(Register in_out, Register in1, Registe #undef BLOCK_COMMENT +// Compress char[] array to byte[]. +void MacroAssembler::char_array_compress(Register src, Register dst, Register len, + XMMRegister tmp1Reg, XMMRegister tmp2Reg, + XMMRegister tmp3Reg, XMMRegister tmp4Reg, + Register tmp5, Register result) { + Label copy_chars_loop, return_length, return_zero, done; + + // rsi: src + // rdi: dst + // rdx: len + // rcx: tmp5 + // rax: result + + // rsi holds start addr of source char[] to be compressed + // rdi holds start addr of destination byte[] + // rdx holds length + + assert(len != result, ""); + + // save length for return + push(len); + + if (UseSSE42Intrinsics) { + Label copy_32_loop, copy_16, copy_tail; + + movl(result, len); + movl(tmp5, 0xff00ff00); // create mask to test for Unicode chars in vectors + + // vectored compression + andl(len, 0xfffffff0); // vector count (in chars) + andl(result, 0x0000000f); // tail count (in chars) + testl(len, len); + jccb(Assembler::zero, copy_16); + + // compress 16 chars per iter + movdl(tmp1Reg, tmp5); + pshufd(tmp1Reg, tmp1Reg, 0); // store Unicode mask in tmp1Reg + pxor(tmp4Reg, tmp4Reg); + + lea(src, Address(src, len, Address::times_2)); + lea(dst, Address(dst, len, Address::times_1)); + negptr(len); + + bind(copy_32_loop); + movdqu(tmp2Reg, Address(src, len, Address::times_2)); // load 1st 8 characters + por(tmp4Reg, tmp2Reg); + movdqu(tmp3Reg, Address(src, len, Address::times_2, 16)); // load next 8 characters + por(tmp4Reg, tmp3Reg); + ptest(tmp4Reg, tmp1Reg); // check for Unicode chars in next vector + jcc(Assembler::notZero, return_zero); + packuswb(tmp2Reg, tmp3Reg); // only ASCII chars; compress each to 1 byte + movdqu(Address(dst, len, Address::times_1), tmp2Reg); + addptr(len, 16); + jcc(Assembler::notZero, copy_32_loop); + + // compress next vector of 8 chars (if any) + bind(copy_16); + movl(len, result); + andl(len, 0xfffffff8); // vector count (in chars) + andl(result, 0x00000007); // tail count (in chars) + testl(len, len); + jccb(Assembler::zero, copy_tail); + + movdl(tmp1Reg, tmp5); + pshufd(tmp1Reg, tmp1Reg, 0); // store Unicode mask in tmp1Reg + pxor(tmp3Reg, tmp3Reg); + + movdqu(tmp2Reg, Address(src, 0)); + ptest(tmp2Reg, tmp1Reg); // check for Unicode chars in vector + jccb(Assembler::notZero, return_zero); + packuswb(tmp2Reg, tmp3Reg); // only LATIN1 chars; compress each to 1 byte + movq(Address(dst, 0), tmp2Reg); + addptr(src, 16); + addptr(dst, 8); + + bind(copy_tail); + movl(len, result); + } + // compress 1 char per iter + testl(len, len); + jccb(Assembler::zero, return_length); + lea(src, Address(src, len, Address::times_2)); + lea(dst, Address(dst, len, Address::times_1)); + negptr(len); + + bind(copy_chars_loop); + load_unsigned_short(result, Address(src, len, Address::times_2)); + testl(result, 0xff00); // check if Unicode char + jccb(Assembler::notZero, return_zero); + movb(Address(dst, len, Address::times_1), result); // ASCII char; compress to 1 byte + increment(len); + jcc(Assembler::notZero, copy_chars_loop); + + // if compression succeeded, return length + bind(return_length); + pop(result); + jmpb(done); + + // if compression failed, return 0 + bind(return_zero); + xorl(result, result); + addptr(rsp, wordSize); + + bind(done); +} + +// Inflate byte[] array to char[]. +void MacroAssembler::byte_array_inflate(Register src, Register dst, Register len, + XMMRegister tmp1, Register tmp2) { + Label copy_chars_loop, done; + + // rsi: src + // rdi: dst + // rdx: len + // rcx: tmp2 + + // rsi holds start addr of source byte[] to be inflated + // rdi holds start addr of destination char[] + // rdx holds length + assert_different_registers(src, dst, len, tmp2); + + if (UseSSE42Intrinsics) { + Label copy_8_loop, copy_bytes, copy_tail; + + movl(tmp2, len); + andl(tmp2, 0x00000007); // tail count (in chars) + andl(len, 0xfffffff8); // vector count (in chars) + jccb(Assembler::zero, copy_tail); + + // vectored inflation + lea(src, Address(src, len, Address::times_1)); + lea(dst, Address(dst, len, Address::times_2)); + negptr(len); + + // inflate 8 chars per iter + bind(copy_8_loop); + pmovzxbw(tmp1, Address(src, len, Address::times_1)); // unpack to 8 words + movdqu(Address(dst, len, Address::times_2), tmp1); + addptr(len, 8); + jcc(Assembler::notZero, copy_8_loop); + + bind(copy_tail); + movl(len, tmp2); + + cmpl(len, 4); + jccb(Assembler::less, copy_bytes); + + movdl(tmp1, Address(src, 0)); // load 4 byte chars + pmovzxbw(tmp1, tmp1); + movq(Address(dst, 0), tmp1); + subptr(len, 4); + addptr(src, 4); + addptr(dst, 8); + + bind(copy_bytes); + } + testl(len, len); + jccb(Assembler::zero, done); + lea(src, Address(src, len, Address::times_1)); + lea(dst, Address(dst, len, Address::times_2)); + negptr(len); + + // inflate 1 char per iter + bind(copy_chars_loop); + load_unsigned_byte(tmp2, Address(src, len, Address::times_1)); // load byte char + movw(Address(dst, len, Address::times_2), tmp2); // inflate byte char to word + increment(len); + jcc(Assembler::notZero, copy_chars_loop); + + bind(done); +} + + Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { switch (cond) { // Note some conditions are synonyms for others diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index c35daaa3d12..1b0185110d7 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -29,7 +29,6 @@ #include "utilities/macros.hpp" #include "runtime/rtmLocking.hpp" - // MacroAssembler extends Assembler by frequently used macros. // // Instructions for which a 'better' code sequence exists depending @@ -1212,32 +1211,50 @@ public: // clear memory of size 'cnt' qwords, starting at 'base'. void clear_mem(Register base, Register cnt, Register rtmp); +#ifdef COMPILER2 + void string_indexof_char(Register str1, Register cnt1, Register ch, Register result, + XMMRegister vec1, XMMRegister vec2, XMMRegister vec3, Register tmp); + // IndexOf strings. // Small strings are loaded through stack if they cross page boundary. void string_indexof(Register str1, Register str2, Register cnt1, Register cnt2, int int_cnt2, Register result, - XMMRegister vec, Register tmp); + XMMRegister vec, Register tmp, + int ae); // IndexOf for constant substrings with size >= 8 elements // which don't need to be loaded through stack. void string_indexofC8(Register str1, Register str2, Register cnt1, Register cnt2, int int_cnt2, Register result, - XMMRegister vec, Register tmp); + XMMRegister vec, Register tmp, + int ae); // Smallest code: we don't need to load through stack, // check string tail. + // helper function for string_compare + void load_next_elements(Register elem1, Register elem2, Register str1, Register str2, + Address::ScaleFactor scale, Address::ScaleFactor scale1, + Address::ScaleFactor scale2, Register index, int ae); // Compare strings. void string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register result, - XMMRegister vec1); + XMMRegister vec1, int ae); - // Compare char[] arrays. - void char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, - Register limit, Register result, Register chr, - XMMRegister vec1, XMMRegister vec2); + // Search for Non-ASCII character (Negative byte value) in a byte array, + // return true if it has any and false otherwise. + void has_negatives(Register ary1, Register len, + Register result, Register tmp1, + XMMRegister vec1, XMMRegister vec2); + + // Compare char[] or byte[] arrays. + void arrays_equals(bool is_array_equ, Register ary1, Register ary2, + Register limit, Register result, Register chr, + XMMRegister vec1, XMMRegister vec2, bool is_char); + +#endif // Fill primitive arrays void generate_fill(BasicType t, bool aligned, @@ -1332,6 +1349,15 @@ public: void fold_8bit_crc32(Register crc, Register table, Register tmp); void fold_8bit_crc32(XMMRegister crc, Register table, XMMRegister xtmp, Register tmp); + // Compress char[] array to byte[]. + void char_array_compress(Register src, Register dst, Register len, + XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3, + XMMRegister tmp4, Register tmp5, Register result); + + // Inflate byte[] array to char[]. + void byte_array_inflate(Register src, Register dst, Register len, + XMMRegister tmp1, Register tmp2); + #undef VIRTUAL }; diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index be97c30acf1..757c263169b 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -63,7 +63,7 @@ static int check_nonzero(const char* xname, int x) { void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, SystemDictionary::WKID klass_id, const char* error_message) { - Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); + InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); KlassHandle klass = SystemDictionary::well_known_klass(klass_id); Register temp = rdi; Register temp2 = noreg; diff --git a/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp b/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp index 4c558b7c3cd..c45dda9a7cf 100644 --- a/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp +++ b/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp @@ -41,7 +41,7 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { which == Assembler::imm_operand, "format unpacks ok"); if (which == Assembler::imm_operand) { if (verify_only) { - assert(*pd_address_in_code() == x, "instructions must match"); + guarantee(*pd_address_in_code() == x, "instructions must match"); } else { *pd_address_in_code() = x; } @@ -50,13 +50,13 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { // both compressed oops and compressed classes look the same if (Universe::heap()->is_in_reserved((oop)x)) { if (verify_only) { - assert(*(uint32_t*) disp == oopDesc::encode_heap_oop((oop)x), "instructions must match"); + guarantee(*(uint32_t*) disp == oopDesc::encode_heap_oop((oop)x), "instructions must match"); } else { *(int32_t*) disp = oopDesc::encode_heap_oop((oop)x); } } else { if (verify_only) { - assert(*(uint32_t*) disp == Klass::encode_klass((Klass*)x), "instructions must match"); + guarantee(*(uint32_t*) disp == Klass::encode_klass((Klass*)x), "instructions must match"); } else { *(int32_t*) disp = Klass::encode_klass((Klass*)x); } @@ -67,14 +67,14 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { address disp = Assembler::locate_operand(ip, which); address next_ip = Assembler::locate_next_instruction(ip); if (verify_only) { - assert(*(int32_t*) disp == (x - next_ip), "instructions must match"); + guarantee(*(int32_t*) disp == (x - next_ip), "instructions must match"); } else { *(int32_t*) disp = x - next_ip; } } #else if (verify_only) { - assert(*pd_address_in_code() == (x + o), "instructions must match"); + guarantee(*pd_address_in_code() == (x + o), "instructions must match"); } else { *pd_address_in_code() = x + o; } diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index e2047549877..564ce75421a 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -1502,7 +1502,7 @@ static void gen_special_dispatch(MacroAssembler* masm, // return to caller // nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, int compile_id, BasicType* in_sig_bt, VMRegPair* in_regs, diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index 0b17c56095c..42d7823405c 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -1694,7 +1694,7 @@ class ComputeMoveOrder: public StackObj { }; static void verify_oop_args(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { Register temp_reg = rbx; // not part of any compiled calling seq @@ -1804,7 +1804,7 @@ static void gen_special_dispatch(MacroAssembler* masm, // return to caller // nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, int compile_id, BasicType* in_sig_bt, VMRegPair* in_regs, diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp index cd5681a44d6..d7d2ced2cf0 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp @@ -147,7 +147,7 @@ uint32_t crc32c_multiply(uint32_t a, uint32_t b) { b_pow_x_table[0] = b; for (int k = 0; k < D; ++k) { // If "a" has non-zero coefficient at x**k,/ add ((b * x**k) mod P) to the result. - if ((a & (uint64_t)(1 << (D - 1 - k))) != 0) product ^= b_pow_x_table[k]; + if ((a & (((uint32_t)1) << (D - 1 - k))) != 0) product ^= b_pow_x_table[k]; // Compute b_pow_x_table[k+1] = (b ** x**(k+1)) mod P. if (b_pow_x_table[k] & 1) { diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp index 82e355f797e..2ca11c6a1d7 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp @@ -1611,7 +1611,7 @@ static jlong double_signflip_pool[2*2]; void TemplateTable::fneg() { transition(ftos, ftos); if (UseSSE >= 1) { - static jlong *float_signflip = double_quadword(&float_signflip_pool[1], 0x8000000080000000, 0x8000000080000000); + static jlong *float_signflip = double_quadword(&float_signflip_pool[1], CONST64(0x8000000080000000), CONST64(0x8000000080000000)); __ xorps(xmm0, ExternalAddress((address) float_signflip)); } else { LP64_ONLY(ShouldNotReachHere()); @@ -1622,7 +1622,8 @@ void TemplateTable::fneg() { void TemplateTable::dneg() { transition(dtos, dtos); if (UseSSE >= 2) { - static jlong *double_signflip = double_quadword(&double_signflip_pool[1], 0x8000000000000000, 0x8000000000000000); + static jlong *double_signflip = + double_quadword(&double_signflip_pool[1], CONST64(0x8000000000000000), CONST64(0x8000000000000000)); __ xorpd(xmm0, ExternalAddress((address) double_signflip)); } else { #ifdef _LP64 diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp index 121ec0a02ac..a337ab14590 100644 --- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp @@ -82,6 +82,7 @@ declare_constant(VM_Version::CPU_AVX512CD) \ declare_constant(VM_Version::CPU_AVX512BW) -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ + declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) #endif // CPU_X86_VM_VMSTRUCTS_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp index d97c681cfc0..94d8a595b52 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp @@ -652,7 +652,7 @@ public: result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu / cores_per_cpu(); } - return result; + return (result == 0 ? 1 : result); } static intx L1_line_size() { diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 75534cf8604..36c2b6fba90 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -11435,16 +11435,62 @@ instruct rep_fast_stosb(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, ins_pipe( pipe_slow ); %} -instruct string_compare(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2, - eAXRegI result, regD tmp1, eFlagsReg cr) %{ +instruct string_compareL(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2, + eAXRegI result, regD tmp1, eFlagsReg cr) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); - format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} ins_encode %{ __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, $result$$Register, - $tmp1$$XMMRegister); + $tmp1$$XMMRegister, StrIntrinsicNode::LL); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_compareU(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2, + eAXRegI result, regD tmp1, eFlagsReg cr) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$XMMRegister, StrIntrinsicNode::UU); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_compareLU(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2, + eAXRegI result, regD tmp1, eFlagsReg cr) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$XMMRegister, StrIntrinsicNode::LU); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_compareUL(eSIRegP str1, eDXRegI cnt1, eDIRegP str2, eCXRegI cnt2, + eAXRegI result, regD tmp1, eFlagsReg cr) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} + ins_encode %{ + __ string_compare($str2$$Register, $str1$$Register, + $cnt2$$Register, $cnt1$$Register, $result$$Register, + $tmp1$$XMMRegister, StrIntrinsicNode::UL); %} ins_pipe( pipe_slow ); %} @@ -11457,21 +11503,50 @@ instruct string_equals(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result, format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %} ins_encode %{ - __ char_arrays_equals(false, $str1$$Register, $str2$$Register, - $cnt$$Register, $result$$Register, $tmp3$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister); + __ arrays_equals(false, $str1$$Register, $str2$$Register, + $cnt$$Register, $result$$Register, $tmp3$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */); + %} + + ins_pipe( pipe_slow ); +%} + +// fast search of substring with known size. +instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2, + eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL)); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + ins_encode %{ + int icnt2 = (int)$int_cnt2$$constant; + if (icnt2 >= 16) { + // IndexOf for constant substrings with size >= 16 elements + // which don't need to be loaded through stack. + __ string_indexofC8($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + } else { + // Small strings are loaded through stack if they cross page boundary. + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + } %} ins_pipe( pipe_slow ); %} // fast search of substring with known size. -instruct string_indexof_con(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2, - eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ - predicate(UseSSE42Intrinsics); +instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2, + eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; if (icnt2 >= 8) { @@ -11480,47 +11555,182 @@ instruct string_indexof_con(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_c __ string_indexofC8($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register); + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); } else { // Small strings are loaded through stack if they cross page boundary. __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register); + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); } %} ins_pipe( pipe_slow ); %} -instruct string_indexof(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, - eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{ - predicate(UseSSE42Intrinsics); +// fast search of substring with known size. +instruct string_indexof_conUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2, + eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL)); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + ins_encode %{ + int icnt2 = (int)$int_cnt2$$constant; + if (icnt2 >= 8) { + // IndexOf for constant substrings with size >= 8 elements + // which don't need to be loaded through stack. + __ string_indexofC8($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + } else { + // Small strings are loaded through stack if they cross page boundary. + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + } + %} + ins_pipe( pipe_slow ); +%} + +instruct string_indexofL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, + eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} + format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, (-1), $result$$Register, - $vec$$XMMRegister, $tmp$$Register); + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_indexofU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, + eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU)); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} + ins_encode %{ + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + (-1), $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_indexofUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, + eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL)); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} + ins_encode %{ + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + (-1), $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_indexofU_char(eDIRegP str1, eDXRegI cnt1, eAXRegI ch, + eBXRegI result, regD vec1, regD vec2, regD vec3, eCXRegI tmp, eFlagsReg cr) %{ + predicate(UseSSE42Intrinsics); + match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); + effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr); + format %{ "String IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %} + ins_encode %{ + __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register, + $vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register); %} ins_pipe( pipe_slow ); %} // fast array equals -instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI result, - regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr) +instruct array_equalsB(eDIRegP ary1, eSIRegP ary2, eAXRegI result, + regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr) %{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (AryEq ary1 ary2)); effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); //ins_cost(300); - format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} + format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} ins_encode %{ - __ char_arrays_equals(true, $ary1$$Register, $ary2$$Register, - $tmp3$$Register, $result$$Register, $tmp4$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister); + __ arrays_equals(true, $ary1$$Register, $ary2$$Register, + $tmp3$$Register, $result$$Register, $tmp4$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */); + %} + ins_pipe( pipe_slow ); +%} + +instruct array_equalsC(eDIRegP ary1, eSIRegP ary2, eAXRegI result, + regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr) +%{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (AryEq ary1 ary2)); + effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); + //ins_cost(300); + + format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} + ins_encode %{ + __ arrays_equals(true, $ary1$$Register, $ary2$$Register, + $tmp3$$Register, $result$$Register, $tmp4$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */); + %} + ins_pipe( pipe_slow ); +%} + +instruct has_negatives(eSIRegP ary1, eCXRegI len, eAXRegI result, + regD tmp1, regD tmp2, eBXRegI tmp3, eFlagsReg cr) +%{ + match(Set result (HasNegatives ary1 len)); + effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr); + + format %{ "has negatives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} + ins_encode %{ + __ has_negatives($ary1$$Register, $len$$Register, + $result$$Register, $tmp3$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +// fast char[] to byte[] compression +instruct string_compress(eSIRegP src, eDIRegP dst, eDXRegI len, regD tmp1, regD tmp2, regD tmp3, regD tmp4, + eCXRegI tmp5, eAXRegI result, eFlagsReg cr) %{ + match(Set result (StrCompressedCopy src (Binary dst len))); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr); + + format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %} + ins_encode %{ + __ char_array_compress($src$$Register, $dst$$Register, $len$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister, + $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register); + %} + ins_pipe( pipe_slow ); +%} + +// fast byte[] to char[] inflation +instruct string_inflate(Universe dummy, eSIRegP src, eDIRegP dst, eDXRegI len, + regD tmp1, eCXRegI tmp2, eFlagsReg cr) %{ + match(Set dummy (StrInflatedCopy src (Binary dst len))); + effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr); + + format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %} + ins_encode %{ + __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register, + $tmp1$$XMMRegister, $tmp2$$Register); %} ins_pipe( pipe_slow ); %} diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 1b78b733361..d63e5b68b20 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -10447,30 +10447,108 @@ instruct rep_fast_stosb(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dum ins_pipe( pipe_slow ); %} -instruct string_compare(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, - rax_RegI result, regD tmp1, rFlagsReg cr) +instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, + rax_RegI result, regD tmp1, rFlagsReg cr) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); - format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} ins_encode %{ __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, $result$$Register, - $tmp1$$XMMRegister); + $tmp1$$XMMRegister, StrIntrinsicNode::LL); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_compareU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, + rax_RegI result, regD tmp1, rFlagsReg cr) +%{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$XMMRegister, StrIntrinsicNode::UU); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_compareLU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, + rax_RegI result, regD tmp1, rFlagsReg cr) +%{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} + ins_encode %{ + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, $result$$Register, + $tmp1$$XMMRegister, StrIntrinsicNode::LU); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_compareUL(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI cnt2, + rax_RegI result, regD tmp1, rFlagsReg cr) +%{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} + ins_encode %{ + __ string_compare($str2$$Register, $str1$$Register, + $cnt2$$Register, $cnt1$$Register, $result$$Register, + $tmp1$$XMMRegister, StrIntrinsicNode::UL); %} ins_pipe( pipe_slow ); %} // fast search of substring with known size. -instruct string_indexof_con(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2, - rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) +instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2, + rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) %{ - predicate(UseSSE42Intrinsics); + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + ins_encode %{ + int icnt2 = (int)$int_cnt2$$constant; + if (icnt2 >= 16) { + // IndexOf for constant substrings with size >= 16 elements + // which don't need to be loaded through stack. + __ string_indexofC8($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + } else { + // Small strings are loaded through stack if they cross page boundary. + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + } + %} + ins_pipe( pipe_slow ); +%} + +// fast search of substring with known size. +instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2, + rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) +%{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU)); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; if (icnt2 >= 8) { @@ -10479,31 +10557,108 @@ instruct string_indexof_con(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI in __ string_indexofC8($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register); + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); } else { // Small strings are loaded through stack if they cross page boundary. __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register); + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); } %} ins_pipe( pipe_slow ); %} -instruct string_indexof(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2, - rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr) +// fast search of substring with known size. +instruct string_indexof_conUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2, + rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) %{ - predicate(UseSSE42Intrinsics); + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL)); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + ins_encode %{ + int icnt2 = (int)$int_cnt2$$constant; + if (icnt2 >= 8) { + // IndexOf for constant substrings with size >= 8 elements + // which don't need to be loaded through stack. + __ string_indexofC8($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + } else { + // Small strings are loaded through stack if they cross page boundary. + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + } + %} + ins_pipe( pipe_slow ); +%} + +instruct string_indexofL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2, + rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr) +%{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} + format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, (-1), $result$$Register, - $vec$$XMMRegister, $tmp$$Register); + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_indexofU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2, + rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr) +%{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU)); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} + ins_encode %{ + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + (-1), $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_indexofUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2, + rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr) +%{ + predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL)); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} + ins_encode %{ + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + (-1), $result$$Register, + $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + %} + ins_pipe( pipe_slow ); +%} + +instruct string_indexofU_char(rdi_RegP str1, rdx_RegI cnt1, rax_RegI ch, + rbx_RegI result, regD vec1, regD vec2, regD vec3, rcx_RegI tmp, rFlagsReg cr) +%{ + predicate(UseSSE42Intrinsics); + match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); + effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr); + format %{ "String IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %} + ins_encode %{ + __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register, + $vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register); %} ins_pipe( pipe_slow ); %} @@ -10517,26 +10672,86 @@ instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI resu format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %} ins_encode %{ - __ char_arrays_equals(false, $str1$$Register, $str2$$Register, - $cnt$$Register, $result$$Register, $tmp3$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister); + __ arrays_equals(false, $str1$$Register, $str2$$Register, + $cnt$$Register, $result$$Register, $tmp3$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */); %} ins_pipe( pipe_slow ); %} // fast array equals -instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, - regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr) +instruct array_equalsB(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, + regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr) %{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (AryEq ary1 ary2)); effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); - //ins_cost(300); - format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} + format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} ins_encode %{ - __ char_arrays_equals(true, $ary1$$Register, $ary2$$Register, - $tmp3$$Register, $result$$Register, $tmp4$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister); + __ arrays_equals(true, $ary1$$Register, $ary2$$Register, + $tmp3$$Register, $result$$Register, $tmp4$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */); + %} + ins_pipe( pipe_slow ); +%} + +instruct array_equalsC(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, + regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr) +%{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (AryEq ary1 ary2)); + effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); + + format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} + ins_encode %{ + __ arrays_equals(true, $ary1$$Register, $ary2$$Register, + $tmp3$$Register, $result$$Register, $tmp4$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */); + %} + ins_pipe( pipe_slow ); +%} + +instruct has_negatives(rsi_RegP ary1, rcx_RegI len, rax_RegI result, + regD tmp1, regD tmp2, rbx_RegI tmp3, rFlagsReg cr) +%{ + match(Set result (HasNegatives ary1 len)); + effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr); + + format %{ "has negatives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} + ins_encode %{ + __ has_negatives($ary1$$Register, $len$$Register, + $result$$Register, $tmp3$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +// fast char[] to byte[] compression +instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, regD tmp1, regD tmp2, regD tmp3, regD tmp4, + rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{ + match(Set result (StrCompressedCopy src (Binary dst len))); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr); + + format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %} + ins_encode %{ + __ char_array_compress($src$$Register, $dst$$Register, $len$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister, + $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register); + %} + ins_pipe( pipe_slow ); +%} + +// fast byte[] to char[] inflation +instruct string_inflate(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len, + regD tmp1, rcx_RegI tmp2, rFlagsReg cr) %{ + match(Set dummy (StrInflatedCopy src (Binary dst len))); + effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr); + + format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %} + ins_encode %{ + __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register, + $tmp1$$XMMRegister, $tmp2$$Register); %} ins_pipe( pipe_slow ); %} diff --git a/hotspot/src/cpu/zero/vm/globals_zero.hpp b/hotspot/src/cpu/zero/vm/globals_zero.hpp index cc46781cd0a..00c9d7e8a94 100644 --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp @@ -69,6 +69,9 @@ define_pd_global(uintx, TypeProfileLevel, 0); define_pd_global(bool, PreserveFramePointer, false); +// No performance work done here yet. +define_pd_global(bool, CompactStrings, false); + #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ \ product(bool, UseFastEmptyMethods, true, \ diff --git a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp index ae217a38b58..3fbe12e94f9 100644 --- a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp +++ b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -76,7 +76,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters( } nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, - methodHandle method, + const methodHandle& method, int compile_id, BasicType *sig_bt, VMRegPair *regs, diff --git a/hotspot/src/cpu/zero/vm/vm_version_zero.cpp b/hotspot/src/cpu/zero/vm/vm_version_zero.cpp index 78c42c79461..eb74a00b587 100644 --- a/hotspot/src/cpu/zero/vm/vm_version_zero.cpp +++ b/hotspot/src/cpu/zero/vm/vm_version_zero.cpp @@ -37,5 +37,9 @@ void VM_Version::initialize() { warning("Unaligned memory access is not available on this CPU"); FLAG_SET_DEFAULT(UseUnalignedAccesses, false); } + // Disable prefetching for Zero + if (! FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + warning("Prefetching is not available for a Zero VM"); + } FLAG_SET_DEFAULT(AllocatePrefetchDistance, 0); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java index 591b3c0eee6..b9ce1192221 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java @@ -22,15 +22,18 @@ */ package jdk.vm.ci.amd64; -import static jdk.vm.ci.code.MemoryBarriers.*; -import static jdk.vm.ci.code.Register.*; +import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; +import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; +import static jdk.vm.ci.code.Register.SPECIAL; -import java.nio.*; -import java.util.*; +import java.nio.ByteOrder; +import java.util.EnumSet; -import jdk.vm.ci.code.*; +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register.RegisterCategory; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.PlatformKind; /** * Represents the AMD64 architecture. @@ -65,9 +68,7 @@ public class AMD64 extends Architecture { r8, r9, r10, r11, r12, r13, r14, r15 }; - private static final int XMM_REFERENCE_MAP_SHIFT = 2; - - public static final RegisterCategory XMM = new RegisterCategory("XMM", cpuRegisters.length, XMM_REFERENCE_MAP_SHIFT); + public static final RegisterCategory XMM = new RegisterCategory("XMM"); // XMM registers public static final Register xmm0 = new Register(16, 0, "xmm0", XMM); @@ -79,8 +80,8 @@ public class AMD64 extends Architecture { public static final Register xmm6 = new Register(22, 6, "xmm6", XMM); public static final Register xmm7 = new Register(23, 7, "xmm7", XMM); - public static final Register xmm8 = new Register(24, 8, "xmm8", XMM); - public static final Register xmm9 = new Register(25, 9, "xmm9", XMM); + public static final Register xmm8 = new Register(24, 8, "xmm8", XMM); + public static final Register xmm9 = new Register(25, 9, "xmm9", XMM); public static final Register xmm10 = new Register(26, 10, "xmm10", XMM); public static final Register xmm11 = new Register(27, 11, "xmm11", XMM); public static final Register xmm12 = new Register(28, 12, "xmm12", XMM); @@ -88,28 +89,77 @@ public class AMD64 extends Architecture { public static final Register xmm14 = new Register(30, 14, "xmm14", XMM); public static final Register xmm15 = new Register(31, 15, "xmm15", XMM); - public static final Register[] xmmRegisters = { + public static final Register xmm16 = new Register(32, 16, "xmm16", XMM); + public static final Register xmm17 = new Register(33, 17, "xmm17", XMM); + public static final Register xmm18 = new Register(34, 18, "xmm18", XMM); + public static final Register xmm19 = new Register(35, 19, "xmm19", XMM); + public static final Register xmm20 = new Register(36, 20, "xmm20", XMM); + public static final Register xmm21 = new Register(37, 21, "xmm21", XMM); + public static final Register xmm22 = new Register(38, 22, "xmm22", XMM); + public static final Register xmm23 = new Register(39, 23, "xmm23", XMM); + + public static final Register xmm24 = new Register(40, 24, "xmm24", XMM); + public static final Register xmm25 = new Register(41, 25, "xmm25", XMM); + public static final Register xmm26 = new Register(42, 26, "xmm26", XMM); + public static final Register xmm27 = new Register(43, 27, "xmm27", XMM); + public static final Register xmm28 = new Register(44, 28, "xmm28", XMM); + public static final Register xmm29 = new Register(45, 29, "xmm29", XMM); + public static final Register xmm30 = new Register(46, 30, "xmm30", XMM); + public static final Register xmm31 = new Register(47, 31, "xmm31", XMM); + + public static final Register[] xmmRegistersSSE = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 }; - public static final Register[] cpuxmmRegisters = { + public static final Register[] xmmRegistersAVX512 = { + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, + xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23, + xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31 + }; + + public static final RegisterCategory MASK = new RegisterCategory("MASK", false); + + public static final Register k0 = new Register(48, 0, "k0", MASK); + public static final Register k1 = new Register(49, 1, "k1", MASK); + public static final Register k2 = new Register(50, 2, "k2", MASK); + public static final Register k3 = new Register(51, 3, "k3", MASK); + public static final Register k4 = new Register(52, 4, "k4", MASK); + public static final Register k5 = new Register(53, 5, "k5", MASK); + public static final Register k6 = new Register(54, 6, "k6", MASK); + public static final Register k7 = new Register(55, 7, "k7", MASK); + + public static final Register[] valueRegistersSSE = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 }; + public static final Register[] valueRegistersAVX512 = { + rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, + r8, r9, r10, r11, r12, r13, r14, r15, + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, + xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23, + xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31, + k0, k1, k2, k3, k4, k5, k6, k7 + }; + /** * Register used to construct an instruction-relative address. */ - public static final Register rip = new Register(32, -1, "rip", SPECIAL); + public static final Register rip = new Register(56, -1, "rip", SPECIAL); public static final Register[] allRegisters = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, + xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23, + xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31, + k0, k1, k2, k3, k4, k5, k6, k7, rip }; @@ -151,7 +201,8 @@ public class AMD64 extends Architecture { AVX512PF, AVX512ER, AVX512CD, - AVX512BW + AVX512BW, + AVX512VL } private final EnumSet features; @@ -166,11 +217,21 @@ public class AMD64 extends Architecture { private final EnumSet flags; + private final AMD64Kind largestKind; + public AMD64(EnumSet features, EnumSet flags) { - super("AMD64", JavaKind.Long, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8); + super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, 8); this.features = features; this.flags = flags; assert features.contains(CPUFeature.SSE2) : "minimum config for x64"; + + if (features.contains(CPUFeature.AVX512F)) { + largestKind = AMD64Kind.V512_QWORD; + } else if (features.contains(CPUFeature.AVX)) { + largestKind = AMD64Kind.V256_QWORD; + } else { + largestKind = AMD64Kind.V128_QWORD; + } } public EnumSet getFeatures() { @@ -182,50 +243,60 @@ public class AMD64 extends Architecture { } @Override - public PlatformKind getPlatformKind(JavaKind javaKind) { - if (javaKind.isObject()) { - return getWordKind(); + public Register[] getAvailableValueRegisters() { + if (features.contains(CPUFeature.AVX512F)) { + return valueRegistersAVX512; } else { - return javaKind; + return valueRegistersSSE; + } + } + + @Override + public PlatformKind getPlatformKind(JavaKind javaKind) { + switch (javaKind) { + case Boolean: + case Byte: + return AMD64Kind.BYTE; + case Short: + case Char: + return AMD64Kind.WORD; + case Int: + return AMD64Kind.DWORD; + case Long: + case Object: + return AMD64Kind.QWORD; + case Float: + return AMD64Kind.SINGLE; + case Double: + return AMD64Kind.DOUBLE; + default: + return null; } } @Override public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { - if (!(platformKind instanceof JavaKind)) { - return false; + AMD64Kind kind = (AMD64Kind) platformKind; + if (kind.isInteger()) { + return category.equals(CPU); + } else if (kind.isXMM()) { + return category.equals(XMM); + } else { + assert kind.isMask(); + return category.equals(MASK); } - - JavaKind kind = (JavaKind) platformKind; - if (category.equals(CPU)) { - switch (kind) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - case Long: - return true; - } - } else if (category.equals(XMM)) { - switch (kind) { - case Float: - case Double: - return true; - } - } - - return false; } @Override - public PlatformKind getLargestStorableKind(RegisterCategory category) { + public AMD64Kind getLargestStorableKind(RegisterCategory category) { if (category.equals(CPU)) { - return JavaKind.Long; + return AMD64Kind.QWORD; } else if (category.equals(XMM)) { - return JavaKind.Double; + return largestKind; + } else if (category.equals(MASK)) { + return AMD64Kind.MASK64; } else { - return JavaKind.Illegal; + return null; } } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64Kind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64Kind.java new file mode 100644 index 00000000000..3896bea7f4f --- /dev/null +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64Kind.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2015, 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.vm.ci.amd64; + +import jdk.vm.ci.meta.PlatformKind; + +public enum AMD64Kind implements PlatformKind { + + // scalar + BYTE(1), + WORD(2), + DWORD(4), + QWORD(8), + SINGLE(4), + DOUBLE(8), + + // SSE2 + V32_BYTE(4, BYTE), + V32_WORD(4, WORD), + V64_BYTE(8, BYTE), + V64_WORD(8, WORD), + V64_DWORD(8, DWORD), + V128_BYTE(16, BYTE), + V128_WORD(16, WORD), + V128_DWORD(16, DWORD), + V128_QWORD(16, QWORD), + V128_SINGLE(16, SINGLE), + V128_DOUBLE(16, DOUBLE), + + // AVX + V256_BYTE(32, BYTE), + V256_WORD(32, WORD), + V256_DWORD(32, DWORD), + V256_QWORD(32, QWORD), + V256_SINGLE(32, SINGLE), + V256_DOUBLE(32, DOUBLE), + + // AVX512 + V512_BYTE(64, BYTE), + V512_WORD(64, WORD), + V512_DWORD(64, DWORD), + V512_QWORD(64, QWORD), + V512_SINGLE(64, SINGLE), + V512_DOUBLE(64, DOUBLE), + + MASK8(1), + MASK16(2), + MASK32(4), + MASK64(8); + + private final int size; + private final int vectorLength; + + private final AMD64Kind scalar; + private final EnumKey key = new EnumKey<>(this); + + private AMD64Kind(int size) { + this.size = size; + this.scalar = this; + this.vectorLength = 1; + } + + private AMD64Kind(int size, AMD64Kind scalar) { + this.size = size; + this.scalar = scalar; + + assert size % scalar.size == 0; + this.vectorLength = size / scalar.size; + } + + public AMD64Kind getScalar() { + return scalar; + } + + public int getSizeInBytes() { + return size; + } + + public int getVectorLength() { + return vectorLength; + } + + public Key getKey() { + return key; + } + + public boolean isInteger() { + switch (this) { + case BYTE: + case WORD: + case DWORD: + case QWORD: + return true; + default: + return false; + } + } + + public boolean isXMM() { + switch (this) { + case SINGLE: + case DOUBLE: + case V32_BYTE: + case V32_WORD: + case V64_BYTE: + case V64_WORD: + case V64_DWORD: + case V128_BYTE: + case V128_WORD: + case V128_DWORD: + case V128_QWORD: + case V128_SINGLE: + case V128_DOUBLE: + case V256_BYTE: + case V256_WORD: + case V256_DWORD: + case V256_QWORD: + case V256_SINGLE: + case V256_DOUBLE: + case V512_BYTE: + case V512_WORD: + case V512_DWORD: + case V512_QWORD: + case V512_SINGLE: + case V512_DOUBLE: + return true; + default: + return false; + } + } + + public boolean isMask() { + switch (this) { + case MASK8: + case MASK16: + case MASK32: + case MASK64: + return true; + default: + return false; + } + } + + public char getTypeChar() { + switch (this) { + case BYTE: + return 'b'; + case WORD: + return 'w'; + case DWORD: + return 'd'; + case QWORD: + return 'q'; + case SINGLE: + return 'S'; + case DOUBLE: + return 'D'; + case V32_BYTE: + case V32_WORD: + case V64_BYTE: + case V64_WORD: + case V64_DWORD: + return 'v'; + case V128_BYTE: + case V128_WORD: + case V128_DWORD: + case V128_QWORD: + case V128_SINGLE: + case V128_DOUBLE: + return 'x'; + case V256_BYTE: + case V256_WORD: + case V256_DWORD: + case V256_QWORD: + case V256_SINGLE: + case V256_DOUBLE: + return 'y'; + case V512_BYTE: + case V512_WORD: + case V512_DWORD: + case V512_QWORD: + case V512_SINGLE: + case V512_DOUBLE: + return 'z'; + case MASK8: + case MASK16: + case MASK32: + case MASK64: + return 'k'; + default: + return '-'; + } + } +} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java index 148d2ac5ec6..10bf6a81fe7 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java @@ -22,11 +22,12 @@ */ package jdk.vm.ci.code; -import java.nio.*; -import java.util.*; +import java.nio.ByteOrder; +import java.util.Arrays; import jdk.vm.ci.code.Register.RegisterCategory; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.PlatformKind; /** * Represents a CPU architecture, including information such as its endianness, CPU registers, word @@ -34,13 +35,6 @@ import jdk.vm.ci.meta.*; */ public abstract class Architecture { - /** - * The number of entries required in a {@link ReferenceMap} covering all the registers that may - * store references. The index of a register in the reference map is given by - * {@link Register#getReferenceMapIndex()}. - */ - private final int registerReferenceMapSize; - /** * The architecture specific type of a native word. */ @@ -85,7 +79,7 @@ public abstract class Architecture { private final int returnAddressSize; protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset, - int registerReferenceMapSize, int returnAddressSize) { + int returnAddressSize) { this.name = name; this.registers = registers; this.wordKind = wordKind; @@ -93,7 +87,6 @@ public abstract class Architecture { this.unalignedMemoryAccess = unalignedMemoryAccess; this.implicitMemoryBarriers = implicitMemoryBarriers; this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset; - this.registerReferenceMapSize = registerReferenceMapSize; this.returnAddressSize = returnAddressSize; } @@ -107,10 +100,6 @@ public abstract class Architecture { return getName().toLowerCase(); } - public int getRegisterReferenceMapSize() { - return registerReferenceMapSize; - } - /** * Gets the natural size of words (typically registers and pointers) of this architecture, in * bytes. @@ -131,13 +120,23 @@ public abstract class Architecture { } /** - * Gets an array of all available registers on this architecture. The index of each register in - * this array is equal to its {@linkplain Register#number number}. + * Gets an array of all registers that exist on this architecture. This contains all registers + * that exist in the specification of this architecture. Not all of them may be available on + * this particular architecture instance. The index of each register in this array is equal to + * its {@linkplain Register#number number}. */ public Register[] getRegisters() { return registers.clone(); } + /** + * Gets an array of all registers available for storing values on this architecture. This may be + * a subset of {@link #getRegisters()}, depending on the capabilities of this particular CPU. + */ + public Register[] getAvailableValueRegisters() { + return getRegisters(); + } + public ByteOrder getByteOrder() { return byteOrder; } @@ -207,7 +206,6 @@ public abstract class Architecture { assert this.byteOrder.equals(that.byteOrder); assert this.implicitMemoryBarriers == that.implicitMemoryBarriers; assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset; - assert this.registerReferenceMapSize == that.registerReferenceMapSize; assert Arrays.equals(this.registers, that.registers); assert this.returnAddressSize == that.returnAddressSize; assert this.unalignedMemoryAccess == that.unalignedMemoryAccess; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java index ad26925cc35..5dffe052997 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.code; -import java.util.*; +import java.util.Locale; /** * Exception thrown when the compiler refuses to compile a method because of problems with the diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java index e51f83ee18c..409601866d6 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java @@ -22,9 +22,12 @@ */ package jdk.vm.ci.code; -import java.util.*; +import java.util.Arrays; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaValue; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.Value; /** * Represents the Java bytecode frame state(s) at a given position including {@link Value locations} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java index a17b427c5bb..1b35f7eb378 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java @@ -22,9 +22,9 @@ */ package jdk.vm.ci.code; -import java.util.*; +import java.util.Objects; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Represents a code position, that is, a chain of inlined methods with bytecode locations, that is diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java index c299c8400de..6161619548b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java @@ -22,9 +22,10 @@ */ package jdk.vm.ci.code; -import static jdk.vm.ci.code.ValueUtil.*; - -import jdk.vm.ci.meta.*; +import static jdk.vm.ci.code.ValueUtil.isAllocatableValue; +import static jdk.vm.ci.code.ValueUtil.isStackSlot; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; /** * A calling convention describes the locations in which the arguments for a call are placed and the diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java index d0007ac08b4..e4f3cae3bee 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java @@ -22,9 +22,14 @@ */ package jdk.vm.ci.code; -import jdk.vm.ci.code.CompilationResult.*; -import jdk.vm.ci.code.DataSection.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.CompilationResult.Call; +import jdk.vm.ci.code.CompilationResult.DataPatch; +import jdk.vm.ci.code.CompilationResult.Mark; +import jdk.vm.ci.code.DataSection.Data; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.SpeculationLog; /** * Access to code cache related details and requirements. @@ -32,26 +37,62 @@ import jdk.vm.ci.meta.*; public interface CodeCacheProvider { /** - * Adds the given compilation result as an implementation of the given method without making it - * the default implementation. + * Installs code for a given method based on a given compilation result without making it the + * default implementation of the method. * - * @param method a method to which the executable code is begin added + * @param method a method implemented by the installed code * @param compResult the compilation result to be added - * @param speculationLog the speculation log to be used - * @return a reference to the compiled and ready-to-run code or throws a - * {@link BailoutException} if the code installation failed + * @param log the speculation log to be used + * @param installedCode a predefined {@link InstalledCode} object to use as a reference to the + * installed code. If {@code null}, a new {@link InstalledCode} object will be + * created. + * @return a reference to the ready-to-run code + * @throws BailoutException if the code installation failed */ - InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode); + default InstalledCode addCode(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode installedCode) { + return installCode(new CompilationRequest(method), compResult, installedCode, log, false); + } /** - * Sets the given compilation result as the default implementation of the given method. + * Installs code for a given method based on a given compilation result and makes it the default + * implementation of the method. * - * @param method a method to which the executable code is begin added + * @param method a method implemented by the installed code and for which the installed code + * becomes the default implementation * @param compResult the compilation result to be added - * @return a reference to the compiled and ready-to-run code or null if the code installation - * failed + * @return a reference to the ready-to-run code + * @throws BailoutException if the code installation failed */ - InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult); + default InstalledCode setDefaultCode(ResolvedJavaMethod method, CompilationResult compResult) { + return installCode(new CompilationRequest(method), compResult, null, null, true); + } + + /** + * Installs code based on a given compilation result. + * + * @param compRequest details of the method compiled to produce {@code compResult} or + * {@code null} if the input to {@code compResult} was not a + * {@link ResolvedJavaMethod} + * @param compResult the compilation result to be added + * @param installedCode a pre-allocated {@link InstalledCode} object to use as a reference to + * the installed code. If {@code null}, a new {@link InstalledCode} object will be + * created. + * @param log the speculation log to be used + * @param isDefault specifies if the installed code should be made the default implementation of + * {@code compRequest.getMethod()}. The default implementation for a method is the + * code executed for standard calls to the method. This argument is ignored if + * {@code compRequest == null}. + * @return a reference to the compiled and ready-to-run installed code + * @throws BailoutException if the code installation failed + */ + InstalledCode installCode(CompilationRequest compRequest, CompilationResult compResult, InstalledCode installedCode, SpeculationLog log, boolean isDefault); + + /** + * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be + * raised the next time {@code installedCode} is + * {@linkplain InstalledCode#executeVarargs(Object...) executed}. + */ + void invalidateInstalledCode(InstalledCode installedCode); /** * Gets a name for a {@link Mark} mark. @@ -102,4 +143,16 @@ public interface CodeCacheProvider { * Create a new speculation log for the target runtime. */ SpeculationLog createSpeculationLog(); + + /** + * Returns the maximum absolute offset of a PC relative call to a given address from any + * position in the code cache or -1 when not applicable. Intended for determining the required + * size of address/offset fields. + */ + long getMaxCallTargetOffset(long address); + + /** + * Determines if debug info should also be emitted at non-safepoint locations. + */ + boolean shouldDebugNonSafepoints(); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java index bae5a53b8e7..a138a30dca2 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java @@ -22,9 +22,15 @@ */ package jdk.vm.ci.code; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MetaUtil; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.Signature; /** * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.code} and its clients. @@ -323,49 +329,12 @@ public class CodeUtil { public interface RefMapFormatter { String formatStackSlot(int frameRefMapIndex); - - String formatRegister(int regRefMapIndex); } /** - * Formats a location in a register reference map. + * Formats a location present in a reference map. */ - public static class DefaultRegFormatter implements RefMapFormatter { - - private final Register[] registers; - - public DefaultRegFormatter(Architecture arch) { - registers = new Register[arch.getRegisterReferenceMapSize()]; - for (Register r : arch.getRegisters()) { - if (r.getReferenceMapIndex() >= 0) { - registers[r.getReferenceMapIndex()] = r; - } - } - } - - public String formatStackSlot(int frameRefMapIndex) { - return null; - } - - public String formatRegister(int regRefMapIndex) { - int i = regRefMapIndex; - int idx = 0; - while (registers[i] == null) { - i--; - idx++; - } - if (idx == 0) { - return registers[i].toString(); - } else { - return String.format("%s+%d", registers[i].toString(), idx); - } - } - } - - /** - * Formats a location present in a register or frame reference map. - */ - public static class DefaultRefMapFormatter extends DefaultRegFormatter { + public static class DefaultRefMapFormatter implements RefMapFormatter { /** * The size of a stack slot. @@ -383,8 +352,7 @@ public class CodeUtil { */ public final int refMapToFPOffset; - public DefaultRefMapFormatter(Architecture arch, int slotSize, Register fp, int refMapToFPOffset) { - super(arch); + public DefaultRefMapFormatter(int slotSize, Register fp, int refMapToFPOffset) { this.slotSize = slotSize; this.fp = fp; this.refMapToFPOffset = refMapToFPOffset; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationRequest.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationRequest.java new file mode 100644 index 00000000000..dabaf04f8b7 --- /dev/null +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationRequest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, 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.vm.ci.code; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * Represents a request to compile a method. + */ +public class CompilationRequest { + + private final ResolvedJavaMethod method; + + private final int entryBCI; + + /** + * Creates a request to compile a method starting at its entry point. + * + * @param method the method to be compiled + */ + public CompilationRequest(ResolvedJavaMethod method) { + this(method, -1); + } + + /** + * Creates a request to compile a method starting at a given BCI. + * + * @param method the method to be compiled + * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the + * method's entry point + */ + public CompilationRequest(ResolvedJavaMethod method, int entryBCI) { + assert method != null; + this.method = method; + this.entryBCI = entryBCI; + } + + /** + * Gets the method to be compiled. + */ + public ResolvedJavaMethod getMethod() { + return method; + } + + /** + * Gets the bytecode index (BCI) at which to start compiling where -1 denotes a non-OSR + * compilation request and all other values denote an on stack replacement (OSR) compilation + * request. + */ + public int getEntryBCI() { + return entryBCI; + } + + @Override + public String toString() { + return method.format("%H.%n(%p)@" + entryBCI); + } +} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java index 5cd3636eaad..9967d0cfdae 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java @@ -22,13 +22,24 @@ */ package jdk.vm.ci.code; -import static java.util.Collections.*; -import static jdk.vm.ci.meta.MetaUtil.*; +import static java.util.Collections.emptyList; +import static java.util.Collections.unmodifiableList; +import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.meta.Assumptions.*; +import jdk.vm.ci.meta.Assumptions.Assumption; +import jdk.vm.ci.meta.InvokeTarget; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.MetaUtil; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.VMConstant; /** * Represents the output from compiling a method, including the compiled machine code, associated @@ -115,8 +126,8 @@ public class CompilationResult { public enum MetaSpaceAccessType { Move, - Store, // store only works for compressed oops (memory <- 32bit value). Compressed oops is - // not supported using AOT. TODO: Look at HotSpotStoreConstantOp + Store, // store only works for compressed oops (memory <- 32bit value). Compressed oops is + // not supported using AOT. TODO: Look at HotSpotStoreConstantOp Compare; // HotSpotCompareMemoryConstantOp, HotSpotCompareConstantOp private MetaSpaceAccessType() { @@ -128,13 +139,11 @@ public class CompilationResult { */ public static final class MetaSpaceAccess extends Infopoint { - private static final long serialVersionUID = 1701958512608684706L; - /** * Metaspace reference. */ public final Object reference; // Object here is a HotSpotResolvedObjectType or a - // HotSpotMetaSpaceConstant + // HotSpotMetaSpaceConstant public final MetaSpaceAccessType type; @@ -296,6 +305,15 @@ public class CompilationResult { } return false; } + + @Override + public String toString() { + if (initialized) { + return String.format("DataSection[0x%x]", offset); + } else { + return "DataSection[?]"; + } + } } /** @@ -528,8 +546,6 @@ public class CompilationResult { } } - private int id = -1; - /** * Specifies whether this compilation is a {@code +ImmutableCode} {@code +GeneratePIC} * compilation. @@ -612,7 +628,6 @@ public class CompilationResult { CompilationResult that = (CompilationResult) obj; // @formatter:off if (this.entryBCI == that.entryBCI && - this.id == that.id && this.customStackAreaOffset == that.customStackAreaOffset && this.totalFrameSize == that.totalFrameSize && this.targetCodeSize == that.targetCodeSize && @@ -632,20 +647,6 @@ public class CompilationResult { return false; } - /** - * @return the compile id - */ - public int getId() { - return id; - } - - /** - * @param id the compile id to set - */ - public void setId(int id) { - this.id = id; - } - /** * @return true is this is a {@code +ImmutableCode} {@code +GeneratePIC} compilation, false * otherwise. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java index d4d28810261..295d4425ac1 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java @@ -22,15 +22,18 @@ */ package jdk.vm.ci.code; -import static jdk.vm.ci.meta.MetaUtil.*; +import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString; -import java.nio.*; -import java.util.*; -import java.util.function.*; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Objects; +import java.util.function.Consumer; -import jdk.vm.ci.code.CompilationResult.*; -import jdk.vm.ci.code.DataSection.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.CompilationResult.DataPatch; +import jdk.vm.ci.code.CompilationResult.DataSectionReference; +import jdk.vm.ci.code.DataSection.Data; +import jdk.vm.ci.meta.SerializableConstant; public final class DataSection implements Iterable { @@ -176,11 +179,27 @@ public final class DataSection implements Iterable { */ public DataSectionReference insertData(Data data) { assert !finalLayout; - if (data.ref == null) { - data.ref = new DataSectionReference(); + synchronized (data) { + if (data.ref == null) { + data.ref = new DataSectionReference(); + dataItems.add(data); + } + return data.ref; + } + } + + /** + * Transfers all {@link Data} from the provided other {@link DataSection} to this + * {@link DataSection}, and empties the other section. + */ + public void addAll(DataSection other) { + assert !finalLayout && !other.finalLayout; + + for (Data data : other.dataItems) { + assert data.ref != null; dataItems.add(data); } - return data.ref; + other.dataItems.clear(); } /** @@ -195,14 +214,16 @@ public final class DataSection implements Iterable { dataItems.sort((a, b) -> a.alignment - b.alignment); int position = 0; + int alignment = 1; for (Data d : dataItems) { - sectionAlignment = lcm(sectionAlignment, d.alignment); + alignment = lcm(alignment, d.alignment); position = align(position, d.alignment); d.ref.setOffset(position); position += d.size; } + sectionAlignment = alignment; sectionSize = position; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java index 60e811f3761..be7729fb76f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.code; -import java.util.*; +import java.util.Objects; /** * Represents the debugging information for a particular point of execution. This information diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java index fe0c84ad1dc..815e0f0f0d4 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java @@ -29,14 +29,19 @@ package jdk.vm.ci.code; public class InstalledCode { /** - * Raw address of this code blob. + * Raw address address of entity representing this installed code. */ - private long address; + protected long address; + + /** + * Raw address of entryPoint of this installed code. + */ + protected long entryPoint; /** * Counts how often the address field was reassigned. */ - private long version; + protected long version; protected final String name; @@ -44,27 +49,29 @@ public class InstalledCode { this.name = name; } - public final void setAddress(long address) { - this.address = address; - version++; - } - /** - * @return the address of this code blob + * @return the address of entity representing this installed code. */ public final long getAddress() { return address; } /** - * @return the address of this code blob + * @return the address of the normal entry point of the installed code. + */ + public final long getEntryPoint() { + return entryPoint; + } + + /** + * @return the version number of this installed code */ public final long getVersion() { return version; } /** - * Returns the name of this code blob. + * Returns the name of this installed code. */ public String getName() { return name; @@ -79,10 +86,19 @@ public class InstalledCode { } /** - * Returns the number of instruction bytes for this code. + * @return true if the code represented by this object is still valid for invocation, false + * otherwise (may happen due to deopt, etc.) */ - public long getCodeSize() { - return 0; + public boolean isValid() { + return entryPoint != 0; + } + + /** + * @return true if the code represented by this object still exists and might have live + * activations, false otherwise (may happen due to deopt, etc.) + */ + public boolean isAlive() { + return address != 0; } /** @@ -92,18 +108,10 @@ public class InstalledCode { return null; } - /** - * @return true if the code represented by this object is still valid, false otherwise (may - * happen due to deopt, etc.) - */ - public boolean isValid() { - return address != 0; - } - /** * Invalidates this installed code such that any subsequent * {@linkplain #executeVarargs(Object...) invocation} will throw an - * {@link InvalidInstalledCodeException}. + * {@link InvalidInstalledCodeException} and all existing invocations will be deoptimized. */ public void invalidate() { throw new UnsupportedOperationException(); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Location.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Location.java index c11cb4df3c9..4e0c58d7208 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Location.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Location.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Register.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Register.java index b6c7e894209..8820fd5cb89 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Register.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Register.java @@ -22,7 +22,8 @@ */ package jdk.vm.ci.code; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.LIRKind; /** * Represents a target machine register. @@ -80,22 +81,15 @@ public final class Register implements Comparable { public static class RegisterCategory { private final String name; - - private final int referenceMapOffset; - private final int referenceMapShift; + private final boolean mayContainReference; public RegisterCategory(String name) { - this(name, 0, 0); + this(name, true); } - public RegisterCategory(String name, int referenceMapOffset) { - this(name, referenceMapOffset, 0); - } - - public RegisterCategory(String name, int referenceMapOffset, int referenceMapShift) { + public RegisterCategory(String name, boolean mayContainReference) { this.name = name; - this.referenceMapOffset = referenceMapOffset; - this.referenceMapShift = referenceMapShift; + this.mayContainReference = mayContainReference; } @Override @@ -112,7 +106,7 @@ public final class Register implements Comparable { public boolean equals(Object obj) { if (obj instanceof RegisterCategory) { RegisterCategory that = (RegisterCategory) obj; - return this.referenceMapOffset == that.referenceMapOffset && this.referenceMapShift == that.referenceMapShift && this.name.equals(that.name); + return this.name.equals(that.name); } return false; } @@ -138,10 +132,10 @@ public final class Register implements Comparable { } /** - * Get the start index of this register in the {@link ReferenceMap}. + * Determine whether this register needs to be part of the reference map. */ - public int getReferenceMapIndex() { - return (encoding << registerCategory.referenceMapShift) + registerCategory.referenceMapOffset; + public boolean mayContainReference() { + return registerCategory.mayContainReference; } /** diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java index 34f1100e553..b8c15075627 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.code; -import java.util.*; +import java.util.Arrays; /** * A collection of register attributes. The specific attribute values for a register may be local to diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java index 57298738551..f942b723dbc 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java @@ -22,8 +22,10 @@ */ package jdk.vm.ci.code; -import jdk.vm.ci.code.CallingConvention.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.CallingConvention.Type; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.PlatformKind; /** * A register configuration binds roles and {@linkplain RegisterAttributes attributes} to physical diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java index 4fe15605776..86b92579654 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java @@ -22,7 +22,11 @@ */ package jdk.vm.ci.code; -import java.util.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.TreeMap; /** * A map from registers to frame slots. This can be used to describe where callee saved registers diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterValue.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterValue.java index b578228ee73..7cea61b4e0a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterValue.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterValue.java @@ -22,7 +22,9 @@ */ package jdk.vm.ci.code; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.LIRKind; /** * Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java index 1fa157a7794..efd65fa4921 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackLockValue.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackLockValue.java index 725650ef152..4460b5c350e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackLockValue.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackLockValue.java @@ -22,9 +22,9 @@ */ package jdk.vm.ci.code; -import static jdk.vm.ci.code.ValueUtil.*; - -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.JavaValue; +import jdk.vm.ci.meta.Value; /** * Represents lock information in the debug information. @@ -32,10 +32,10 @@ import jdk.vm.ci.meta.*; public final class StackLockValue implements JavaValue { private JavaValue owner; - private StackSlotValue slot; + private AllocatableValue slot; private final boolean eliminated; - public StackLockValue(JavaValue object, StackSlotValue slot, boolean eliminated) { + public StackLockValue(JavaValue object, AllocatableValue slot, boolean eliminated) { this.owner = object; this.slot = slot; this.eliminated = eliminated; @@ -81,8 +81,7 @@ public final class StackLockValue implements JavaValue { return false; } - public void setSlot(StackSlotValue stackSlot) { - assert slot == null || (isVirtualStackSlot(slot) && (slot.equals(stackSlot) || isStackSlot(stackSlot))) : String.format("Can not set slot for %s to %s", this, stackSlot); + public void setSlot(AllocatableValue stackSlot) { slot = stackSlot; } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlot.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlot.java index edf6f45a360..3ddde182b01 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlot.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, 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 @@ -22,13 +22,14 @@ */ package jdk.vm.ci.code; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.LIRKind; /** * Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an * incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}. */ -public final class StackSlot extends StackSlotValue { +public final class StackSlot extends AllocatableValue { private final int offset; private final boolean addFrameSize; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/TargetDescription.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/TargetDescription.java index d6da8b88514..edd26878d25 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/TargetDescription.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/TargetDescription.java @@ -22,9 +22,10 @@ */ package jdk.vm.ci.code; -import static jdk.vm.ci.meta.MetaUtil.*; - -import jdk.vm.ci.meta.*; +import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.LIRKind; +import jdk.vm.ci.meta.PlatformKind; /** * Represents the target machine for a compiler, including the CPU architecture, the size of @@ -50,9 +51,9 @@ public class TargetDescription { public final int wordSize; /** - * The kind to be used for representing raw pointers and CPU registers. + * The {@link JavaKind} to be used for representing raw pointers and CPU registers in Java code. */ - public final JavaKind wordKind; + public final JavaKind wordJavaKind; /** * The stack alignment requirement of the platform. For example, from Appendix D of (b & MASK); - } - - /** - * Unsigned comparison aboveOrEqual for two numbers. - */ - public static boolean aboveOrEqual(int a, int b) { - return (a & MASK) >= (b & MASK); - } - - /** - * Unsigned comparison belowThan for two numbers. - */ - public static boolean belowThan(int a, int b) { - return (a & MASK) < (b & MASK); - } - - /** - * Unsigned comparison belowOrEqual for two numbers. - */ - public static boolean belowOrEqual(int a, int b) { - return (a & MASK) <= (b & MASK); - } - - /** - * Unsigned comparison aboveThan for two numbers. - */ - public static boolean aboveThan(long a, long b) { - return (a > b) ^ ((a < 0) != (b < 0)); - } - - /** - * Unsigned comparison aboveOrEqual for two numbers. - */ - public static boolean aboveOrEqual(long a, long b) { - return (a >= b) ^ ((a < 0) != (b < 0)); - } - - /** - * Unsigned comparison belowThan for two numbers. - */ - public static boolean belowThan(long a, long b) { - return (a < b) ^ ((a < 0) != (b < 0)); - } - - /** - * Unsigned comparison belowOrEqual for two numbers. - */ - public static boolean belowOrEqual(long a, long b) { - return (a <= b) ^ ((a < 0) != (b < 0)); - } - - /** - * Unsigned division for two numbers. - */ - public static int divide(int a, int b) { - return (int) ((a & MASK) / (b & MASK)); - } - - /** - * Unsigned remainder for two numbers. - */ - public static int remainder(int a, int b) { - return (int) ((a & MASK) % (b & MASK)); - } - - /** - * Unsigned division for two numbers. - */ - public static long divide(long a, long b) { - return bi(a).divide(bi(b)).longValue(); - } - - /** - * Unsigned remainder for two numbers. - */ - public static long remainder(long a, long b) { - return bi(a).remainder(bi(b)).longValue(); - } - - private static BigInteger bi(long unsigned) { - return unsigned >= 0 ? BigInteger.valueOf(unsigned) : BigInteger.valueOf(unsigned & 0x7fffffffffffffffL).setBit(63); - } -} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueUtil.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueUtil.java index 982617d46bb..20bde745829 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueUtil.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueUtil.java @@ -22,9 +22,14 @@ */ package jdk.vm.ci.code; -import java.util.*; +import java.util.ArrayList; +import java.util.List; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaValue; +import jdk.vm.ci.meta.PlatformKind; +import jdk.vm.ci.meta.Value; /** * Utility class for working with the {@link Value} class and its subclasses. @@ -60,6 +65,11 @@ public final class ValueUtil { return value instanceof JavaConstant; } + public static JavaConstant asConstantJavaValue(JavaValue value) { + assert value != null; + return (JavaConstant) value; + } + public static boolean isAllocatableValue(Value value) { assert value != null; return value instanceof AllocatableValue; @@ -80,26 +90,6 @@ public final class ValueUtil { return (StackSlot) value; } - public static boolean isStackSlotValue(Value value) { - assert value != null; - return value instanceof StackSlotValue; - } - - public static StackSlotValue asStackSlotValue(Value value) { - assert value != null; - return (StackSlotValue) value; - } - - public static boolean isVirtualStackSlot(Value value) { - assert value != null; - return value instanceof VirtualStackSlot; - } - - public static VirtualStackSlot asVirtualStackSlot(Value value) { - assert value != null; - return (VirtualStackSlot) value; - } - public static boolean isRegister(Value value) { assert value != null; return value instanceof RegisterValue; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java index 047d84b3850..7b4b2e60af7 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java @@ -22,9 +22,15 @@ */ package jdk.vm.ci.code; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Set; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaValue; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; /** * An instance of this class represents an object whose allocation was removed by escape analysis. @@ -134,45 +140,6 @@ public final class VirtualObject implements JavaValue { return id; } - private boolean checkValues() { - assert (values == null) == (slotKinds == null); - if (values != null) { - assert values.length == slotKinds.length; - if (!type.isArray()) { - ResolvedJavaField[] fields = type.getInstanceFields(true); - int fieldIndex = 0; - for (int i = 0; i < values.length; i++) { - ResolvedJavaField field = fields[fieldIndex++]; - JavaKind valKind = slotKinds[i].getStackKind(); - if (field.getJavaKind() == JavaKind.Object) { - assert valKind.isObject() : field + ": " + valKind + " != " + field.getJavaKind(); - } else { - if ((valKind == JavaKind.Double || valKind == JavaKind.Long) && field.getJavaKind() == JavaKind.Int) { - assert fields[fieldIndex].getJavaKind() == JavaKind.Int; - fieldIndex++; - } else { - assert valKind == field.getJavaKind().getStackKind() : field + ": " + valKind + " != " + field.getJavaKind(); - } - } - } - assert fields.length == fieldIndex : type + ": fields=" + Arrays.toString(fields) + ", field values=" + Arrays.toString(values); - } else { - JavaKind componentKind = type.getComponentType().getJavaKind().getStackKind(); - if (componentKind == JavaKind.Object) { - for (int i = 0; i < values.length; i++) { - assert slotKinds[i].isObject() : slotKinds[i] + " != " + componentKind; - } - } else { - for (int i = 0; i < values.length; i++) { - assert slotKinds[i] == componentKind || componentKind.getBitCount() >= slotKinds[i].getBitCount() || - (componentKind == JavaKind.Int && slotKinds[i].getBitCount() >= JavaKind.Int.getBitCount()) : slotKinds[i] + " != " + componentKind; - } - } - } - } - return true; - } - /** * Overwrites the current set of values with a new one. * @@ -183,7 +150,6 @@ public final class VirtualObject implements JavaValue { public void setValues(JavaValue[] values, JavaKind[] slotKinds) { this.values = values; this.slotKinds = slotKinds; - assert checkValues(); } @Override diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualStackSlot.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualStackSlot.java deleted file mode 100644 index 14d2659bfbc..00000000000 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualStackSlot.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2014, 2014, 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.vm.ci.code; - -import jdk.vm.ci.meta.*; - -/** - * {@link VirtualStackSlot}s are stack slots that are not yet fixed to specific frame offset. They - * are replaced by real {@link StackSlot}s with a fixed position in the frame before code emission. - */ -public abstract class VirtualStackSlot extends StackSlotValue { - - private final int id; - - public VirtualStackSlot(int id, LIRKind lirKind) { - super(lirKind); - this.id = id; - } - - public int getId() { - return id; - } - - @Override - public String toString() { - return "vstack:" + id + getKindSuffix(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + id; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - VirtualStackSlot other = (VirtualStackSlot) obj; - if (id != other.id) { - return false; - } - return true; - } - -} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/package-info.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/package-info.java index 1010108f3ee..63f1ea5df74 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/package-info.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/package-info.java @@ -18,10 +18,10 @@ * if you need additional information or have any questions. */ /** - * Package that defines the interface between a Java application that wants to install code and the - * runtime. The runtime provides in implementation of the {@link jdk.vm.ci.code.CodeCacheProvider} - * interface. The method - * {@link jdk.vm.ci.code.CodeCacheProvider#addMethod(jdk.vm.ci.meta.ResolvedJavaMethod, CompilationResult, jdk.vm.ci.meta.SpeculationLog, InstalledCode)} - * can be used to install code for a given method. + * Package that defines the interface between a Java application that wants to install code and the runtime. + * The runtime provides in implementation of the {@link jdk.vm.ci.code.CodeCacheProvider} interface. + * The method {@link jdk.vm.ci.code.CodeCacheProvider#addCode(jdk.vm.ci.meta.ResolvedJavaMethod, CompilationResult, jdk.vm.ci.meta.SpeculationLog, InstalledCode)} + * can be used to install code. */ package jdk.vm.ci.code; + diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrame.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrame.java index 318e133133e..7453b69fd92 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrame.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrame.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.code.stack; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ResolvedJavaMethod; public interface InspectedFrame { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/StackIntrospection.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/StackIntrospection.java index 99f7e4fe59d..3c48c1dc77f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/StackIntrospection.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/StackIntrospection.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.code.stack; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ResolvedJavaMethod; public interface StackIntrospection { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/JVMCIError.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/JVMCIError.java index 3c53a309a9f..485d2c65a3a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/JVMCIError.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/JVMCIError.java @@ -22,7 +22,8 @@ */ package jdk.vm.ci.common; -import java.util.*; +import java.util.ArrayList; +import java.util.Locale; /** * Indicates a condition in JVMCI related code that should never occur during normal operation. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/Compiler.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/Compiler.java deleted file mode 100644 index 8b07d6747ef..00000000000 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/Compiler.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2015, 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.vm.ci.compiler; - -import jdk.vm.ci.meta.*; -import jdk.vm.ci.options.*; - -public interface Compiler { - int INVOCATION_ENTRY_BCI = -1; - - @Option(help = "", type = OptionType.Debug) OptionValue PrintFilter = new OptionValue<>(null); - @Option(help = "", type = OptionType.Debug) OptionValue PrintCompilation = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) OptionValue PrintAfterCompilation = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) OptionValue PrintBailout = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) OptionValue ExitVMOnBailout = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) OptionValue ExitVMOnException = new OptionValue<>(true); - @Option(help = "", type = OptionType.Debug) OptionValue PrintStackTraceOnException = new OptionValue<>(false); - - /** - * Request the compilation of a method by this JVMCI compiler. The compiler should compile the - * method to machine code and install it in the code cache if the compilation is successful. - * - * @param method the method that should be compiled - * @param entryBCI the BCI at which to start compiling where -1 denotes a non-OSR compilation - * request and all other values denote an OSR compilation request - * @param jvmciEnv pointer to native {@code JVMCIEnv} object - * @param id a unique identifier for this compilation - */ - void compileMethod(ResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id); -} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index 54138bb92e1..d5d31ea86e5 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -22,18 +22,26 @@ */ package jdk.vm.ci.hotspot.amd64; -import static jdk.vm.ci.inittimer.InitTimer.*; +import static jdk.vm.ci.inittimer.InitTimer.timer; -import java.util.*; +import java.util.EnumSet; -import jdk.vm.ci.amd64.*; -import jdk.vm.ci.code.*; -import jdk.vm.ci.compiler.*; -import jdk.vm.ci.hotspot.*; -import jdk.vm.ci.inittimer.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.runtime.*; -import jdk.vm.ci.service.*; +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.code.stack.StackIntrospection; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; +import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider; +import jdk.vm.ci.hotspot.HotSpotStackIntrospection; +import jdk.vm.ci.hotspot.HotSpotVMConfig; +import jdk.vm.ci.inittimer.InitTimer; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.runtime.JVMCIBackend; +import jdk.vm.ci.service.ServiceProvider; @ServiceProvider(HotSpotJVMCIBackendFactory.class) public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory { @@ -68,6 +76,9 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto if ((config.x86CPUFeatures & config.cpuLZCNT) != 0) { features.add(AMD64.CPUFeature.LZCNT); } + if ((config.x86CPUFeatures & config.cpuERMS) != 0) { + features.add(AMD64.CPUFeature.ERMS); + } if ((config.x86CPUFeatures & config.cpuAVX) != 0) { features.add(AMD64.CPUFeature.AVX); } @@ -77,12 +88,42 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto if ((config.x86CPUFeatures & config.cpuAES) != 0) { features.add(AMD64.CPUFeature.AES); } - if ((config.x86CPUFeatures & config.cpuERMS) != 0) { - features.add(AMD64.CPUFeature.ERMS); + if ((config.x86CPUFeatures & config.cpu3DNOWPREFETCH) != 0) { + features.add(AMD64.CPUFeature.AMD_3DNOW_PREFETCH); } if ((config.x86CPUFeatures & config.cpuBMI1) != 0) { features.add(AMD64.CPUFeature.BMI1); } + if ((config.x86CPUFeatures & config.cpuBMI2) != 0) { + features.add(AMD64.CPUFeature.BMI2); + } + if ((config.x86CPUFeatures & config.cpuRTM) != 0) { + features.add(AMD64.CPUFeature.RTM); + } + if ((config.x86CPUFeatures & config.cpuADX) != 0) { + features.add(AMD64.CPUFeature.ADX); + } + if ((config.x86CPUFeatures & config.cpuAVX512F) != 0) { + features.add(AMD64.CPUFeature.AVX512F); + } + if ((config.x86CPUFeatures & config.cpuAVX512DQ) != 0) { + features.add(AMD64.CPUFeature.AVX512DQ); + } + if ((config.x86CPUFeatures & config.cpuAVX512PF) != 0) { + features.add(AMD64.CPUFeature.AVX512PF); + } + if ((config.x86CPUFeatures & config.cpuAVX512ER) != 0) { + features.add(AMD64.CPUFeature.AVX512ER); + } + if ((config.x86CPUFeatures & config.cpuAVX512CD) != 0) { + features.add(AMD64.CPUFeature.AVX512CD); + } + if ((config.x86CPUFeatures & config.cpuAVX512BW) != 0) { + features.add(AMD64.CPUFeature.AVX512BW); + } + if ((config.x86CPUFeatures & config.cpuAVX512VL) != 0) { + features.add(AMD64.CPUFeature.AVX512VL); + } return features; } @@ -97,12 +138,12 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto return flags; } - protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) { + protected TargetDescription createTarget(HotSpotVMConfig config) { final int stackFrameAlignment = 16; final int implicitNullCheckLimit = 4096; final boolean inlineObjects = true; Architecture arch = new AMD64(computeFeatures(config), computeFlags(config)); - return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); } protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntimeProvider runtime) { @@ -132,15 +173,16 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto } @SuppressWarnings("try") - public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) { + public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) { assert host == null; - TargetDescription target = createTarget(runtime.getConfig(), compilerFactory); + TargetDescription target = createTarget(runtime.getConfig()); RegisterConfig regConfig; HotSpotCodeCacheProvider codeCache; ConstantReflectionProvider constantReflection; HotSpotMetaAccessProvider metaAccess; + StackIntrospection stackIntrospection; try (InitTimer t = timer("create providers")) { try (InitTimer rt = timer("create MetaAccess provider")) { metaAccess = createMetaAccess(runtime); @@ -154,13 +196,16 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto try (InitTimer rt = timer("create ConstantReflection provider")) { constantReflection = createConstantReflection(runtime); } + try (InitTimer rt = timer("create StackIntrospection provider")) { + stackIntrospection = new HotSpotStackIntrospection(runtime); + } } try (InitTimer rt = timer("instantiate backend")) { - return createBackend(metaAccess, codeCache, constantReflection); + return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection); } } - protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection) { - return new JVMCIBackend(metaAccess, codeCache, constantReflection); + protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, StackIntrospection stackIntrospection) { + return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection); } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java index 6804a5eaa61..876263c75ef 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java @@ -22,16 +22,47 @@ */ package jdk.vm.ci.hotspot.amd64; -import static jdk.vm.ci.amd64.AMD64.*; +import static jdk.vm.ci.amd64.AMD64.r12; +import static jdk.vm.ci.amd64.AMD64.r15; +import static jdk.vm.ci.amd64.AMD64.r8; +import static jdk.vm.ci.amd64.AMD64.r9; +import static jdk.vm.ci.amd64.AMD64.rax; +import static jdk.vm.ci.amd64.AMD64.rcx; +import static jdk.vm.ci.amd64.AMD64.rdi; +import static jdk.vm.ci.amd64.AMD64.rdx; +import static jdk.vm.ci.amd64.AMD64.rsi; +import static jdk.vm.ci.amd64.AMD64.rsp; +import static jdk.vm.ci.amd64.AMD64.xmm0; +import static jdk.vm.ci.amd64.AMD64.xmm1; +import static jdk.vm.ci.amd64.AMD64.xmm2; +import static jdk.vm.ci.amd64.AMD64.xmm3; +import static jdk.vm.ci.amd64.AMD64.xmm4; +import static jdk.vm.ci.amd64.AMD64.xmm5; +import static jdk.vm.ci.amd64.AMD64.xmm6; +import static jdk.vm.ci.amd64.AMD64.xmm7; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; -import jdk.vm.ci.amd64.*; -import jdk.vm.ci.code.*; -import jdk.vm.ci.code.CallingConvention.*; -import jdk.vm.ci.common.*; -import jdk.vm.ci.hotspot.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.code.CallingConvention.Type; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterAttributes; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.StackSlot; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.hotspot.HotSpotVMConfig; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.LIRKind; +import jdk.vm.ci.meta.PlatformKind; +import jdk.vm.ci.meta.Value; public class AMD64HotSpotRegisterConfig implements RegisterConfig { @@ -86,28 +117,30 @@ public class AMD64HotSpotRegisterConfig implements RegisterConfig { */ private final boolean needsNativeStackHomeSpace; - private static Register[] initAllocatable(boolean reserveForHeapBase) { - Register[] registers = null; - // @formatter:off - if (reserveForHeapBase) { - registers = new Register[] { - rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9, r10, r11, /*r12,*/ r13, r14, /*r15, */ - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - } else { - registers = new Register[] { - rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, /*r15, */ - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; + private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) { + Register[] allRegisters = arch.getAvailableValueRegisters(); + Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 3 : 2)]; + + int idx = 0; + for (Register reg : allRegisters) { + if (reg.equals(rsp) || reg.equals(r15)) { + // skip stack pointer and thread register + continue; + } + if (reserveForHeapBase && reg.equals(r12)) { + // skip heap base register + continue; + } + + registers[idx++] = reg; } - // @formatter:on + + assert idx == registers.length; return registers; } public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) { - this(architecture, config, initAllocatable(config.useCompressedOops)); + this(architecture, config, initAllocatable(architecture, config.useCompressedOops)); assert callerSaved.length >= allocatable.length; } @@ -125,7 +158,7 @@ public class AMD64HotSpotRegisterConfig implements RegisterConfig { this.needsNativeStackHomeSpace = false; } - this.allocatable = allocatable.clone(); + this.allocatable = allocatable; Set callerSaveSet = new HashSet<>(); Collections.addAll(callerSaveSet, allocatable); Collections.addAll(callerSaveSet, xmmParameterRegisters); @@ -134,7 +167,7 @@ public class AMD64HotSpotRegisterConfig implements RegisterConfig { callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]); allAllocatableAreCallerSaved = true; - attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters); + attributesMap = RegisterAttributes.createMap(this, architecture.getRegisters()); } @Override @@ -221,7 +254,7 @@ public class AMD64HotSpotRegisterConfig implements RegisterConfig { if (locations[i] == null) { LIRKind lirKind = target.getLIRKind(kind); locations[i] = StackSlot.get(lirKind, currentStackOffset, !type.out); - currentStackOffset += Math.max(target.getSizeInBytes(lirKind.getPlatformKind()), target.wordSize); + currentStackOffset += Math.max(lirKind.getPlatformKind().getSizeInBytes(), target.wordSize); } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java index 0f26eb6ca22..d9339c2fa7e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java @@ -22,28 +22,36 @@ */ package jdk.vm.ci.hotspot.sparc; -import static jdk.vm.ci.inittimer.InitTimer.*; +import static jdk.vm.ci.inittimer.InitTimer.timer; -import java.util.*; +import java.util.EnumSet; -import jdk.vm.ci.code.*; -import jdk.vm.ci.compiler.*; -import jdk.vm.ci.hotspot.*; -import jdk.vm.ci.inittimer.*; -import jdk.vm.ci.runtime.*; -import jdk.vm.ci.service.*; -import jdk.vm.ci.sparc.*; +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.code.stack.StackIntrospection; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; +import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider; +import jdk.vm.ci.hotspot.HotSpotStackIntrospection; +import jdk.vm.ci.hotspot.HotSpotVMConfig; +import jdk.vm.ci.inittimer.InitTimer; +import jdk.vm.ci.runtime.JVMCIBackend; +import jdk.vm.ci.service.ServiceProvider; +import jdk.vm.ci.sparc.SPARC; import jdk.vm.ci.sparc.SPARC.CPUFeature; @ServiceProvider(HotSpotJVMCIBackendFactory.class) public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory { - protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) { + protected TargetDescription createTarget(HotSpotVMConfig config) { final int stackFrameAlignment = 16; final int implicitNullCheckLimit = 4096; final boolean inlineObjects = false; Architecture arch = new SPARC(computeFeatures(config)); - return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); } protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) { @@ -64,8 +72,62 @@ public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto if ((config.sparcFeatures & config.cbcondInstructions) != 0) { features.add(CPUFeature.CBCOND); } - if (config.useBlockZeroing) { - features.add(CPUFeature.BLOCK_ZEROING); + if ((config.sparcFeatures & config.v8Instructions) != 0) { + features.add(CPUFeature.V8); + } + if ((config.sparcFeatures & config.hardwareMul32) != 0) { + features.add(CPUFeature.HARDWARE_MUL32); + } + if ((config.sparcFeatures & config.hardwareDiv32) != 0) { + features.add(CPUFeature.HARDWARE_DIV32); + } + if ((config.sparcFeatures & config.hardwareFsmuld) != 0) { + features.add(CPUFeature.HARDWARE_FSMULD); + } + if ((config.sparcFeatures & config.hardwarePopc) != 0) { + features.add(CPUFeature.HARDWARE_POPC); + } + if ((config.sparcFeatures & config.v9Instructions) != 0) { + features.add(CPUFeature.V9); + } + if ((config.sparcFeatures & config.sun4v) != 0) { + features.add(CPUFeature.SUN4V); + } + if ((config.sparcFeatures & config.blkInitInstructions) != 0) { + features.add(CPUFeature.BLK_INIT_INSTRUCTIONS); + } + if ((config.sparcFeatures & config.fmafInstructions) != 0) { + features.add(CPUFeature.FMAF); + } + if ((config.sparcFeatures & config.fmauInstructions) != 0) { + features.add(CPUFeature.FMAU); + } + if ((config.sparcFeatures & config.sparc64Family) != 0) { + features.add(CPUFeature.SPARC64_FAMILY); + } + if ((config.sparcFeatures & config.mFamily) != 0) { + features.add(CPUFeature.M_FAMILY); + } + if ((config.sparcFeatures & config.tFamily) != 0) { + features.add(CPUFeature.T_FAMILY); + } + if ((config.sparcFeatures & config.t1Model) != 0) { + features.add(CPUFeature.T1_MODEL); + } + if ((config.sparcFeatures & config.sparc5Instructions) != 0) { + features.add(CPUFeature.SPARC5); + } + if ((config.sparcFeatures & config.aesInstructions) != 0) { + features.add(CPUFeature.SPARC64_FAMILY); + } + if ((config.sparcFeatures & config.sha1Instruction) != 0) { + features.add(CPUFeature.SHA1); + } + if ((config.sparcFeatures & config.sha256Instruction) != 0) { + features.add(CPUFeature.SHA256); + } + if ((config.sparcFeatures & config.sha512Instruction) != 0) { + features.add(CPUFeature.SHA512); } return features; } @@ -81,20 +143,22 @@ public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto } @SuppressWarnings("try") - public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) { + public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) { assert host == null; - TargetDescription target = createTarget(runtime.getConfig(), compilerFactory); + TargetDescription target = createTarget(runtime.getConfig()); HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime); - RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target, runtime.getConfig()); + RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target.arch, runtime.getConfig()); HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target, regConfig); HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime); + StackIntrospection stackIntrospection = new HotSpotStackIntrospection(runtime); try (InitTimer rt = timer("instantiate backend")) { - return createBackend(metaAccess, codeCache, constantReflection); + return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection); } } - protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotConstantReflectionProvider constantReflection) { - return new JVMCIBackend(metaAccess, codeCache, constantReflection); + protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotConstantReflectionProvider constantReflection, + StackIntrospection stackIntrospection) { + return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection); } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java index cb47b2ea564..58dfcdc3e55 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java @@ -22,16 +22,72 @@ */ package jdk.vm.ci.hotspot.sparc; -import static jdk.vm.ci.sparc.SPARC.*; +import static jdk.vm.ci.code.CallingConvention.Type.JavaCall; +import static jdk.vm.ci.code.CallingConvention.Type.JavaCallee; +import static jdk.vm.ci.code.CallingConvention.Type.NativeCall; +import static jdk.vm.ci.meta.JavaKind.Void; +import static jdk.vm.ci.meta.Value.ILLEGAL; +import static jdk.vm.ci.sparc.SPARC.REGISTER_SAFE_AREA_SIZE; +import static jdk.vm.ci.sparc.SPARC.d0; +import static jdk.vm.ci.sparc.SPARC.d2; +import static jdk.vm.ci.sparc.SPARC.d4; +import static jdk.vm.ci.sparc.SPARC.d6; +import static jdk.vm.ci.sparc.SPARC.f0; +import static jdk.vm.ci.sparc.SPARC.f1; +import static jdk.vm.ci.sparc.SPARC.f2; +import static jdk.vm.ci.sparc.SPARC.f3; +import static jdk.vm.ci.sparc.SPARC.f4; +import static jdk.vm.ci.sparc.SPARC.f5; +import static jdk.vm.ci.sparc.SPARC.f6; +import static jdk.vm.ci.sparc.SPARC.f7; +import static jdk.vm.ci.sparc.SPARC.g0; +import static jdk.vm.ci.sparc.SPARC.g2; +import static jdk.vm.ci.sparc.SPARC.g6; +import static jdk.vm.ci.sparc.SPARC.i0; +import static jdk.vm.ci.sparc.SPARC.i1; +import static jdk.vm.ci.sparc.SPARC.i2; +import static jdk.vm.ci.sparc.SPARC.i3; +import static jdk.vm.ci.sparc.SPARC.i4; +import static jdk.vm.ci.sparc.SPARC.i5; +import static jdk.vm.ci.sparc.SPARC.i6; +import static jdk.vm.ci.sparc.SPARC.i7; +import static jdk.vm.ci.sparc.SPARC.l0; +import static jdk.vm.ci.sparc.SPARC.l1; +import static jdk.vm.ci.sparc.SPARC.l2; +import static jdk.vm.ci.sparc.SPARC.l3; +import static jdk.vm.ci.sparc.SPARC.l4; +import static jdk.vm.ci.sparc.SPARC.l5; +import static jdk.vm.ci.sparc.SPARC.l6; +import static jdk.vm.ci.sparc.SPARC.l7; +import static jdk.vm.ci.sparc.SPARC.o0; +import static jdk.vm.ci.sparc.SPARC.o1; +import static jdk.vm.ci.sparc.SPARC.o2; +import static jdk.vm.ci.sparc.SPARC.o3; +import static jdk.vm.ci.sparc.SPARC.o4; +import static jdk.vm.ci.sparc.SPARC.o5; +import static jdk.vm.ci.sparc.SPARC.sp; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; -import jdk.vm.ci.code.*; -import jdk.vm.ci.code.CallingConvention.*; -import jdk.vm.ci.common.*; -import jdk.vm.ci.hotspot.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.sparc.*; +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.code.CallingConvention.Type; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterAttributes; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.StackSlot; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.hotspot.HotSpotVMConfig; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.LIRKind; +import jdk.vm.ci.meta.PlatformKind; +import jdk.vm.ci.sparc.SPARC; public class SPARCHotSpotRegisterConfig implements RegisterConfig { @@ -41,6 +97,11 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig { private final RegisterAttributes[] attributesMap; + /** + * Does native code (C++ code) spill arguments in registers to the parent frame? + */ + private final boolean addNativeRegisterArgumentSlots; + @Override public Register[] getAllocatableRegisters() { return allocatable.clone(); @@ -50,22 +111,9 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig { ArrayList list = new ArrayList<>(); for (Register reg : registers) { if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) { - // Special treatment for double precision - // TODO: This is wasteful it uses only half of the registers as float. - if (kind == JavaKind.Double) { - if (reg.getRegisterCategory().equals(FPUd)) { - list.add(reg); - } - } else if (kind == JavaKind.Float) { - if (reg.getRegisterCategory().equals(FPUs)) { - list.add(reg); - } - } else { - list.add(reg); - } + list.add(reg); } } - Register[] ret = list.toArray(new Register[list.size()]); return ret; } @@ -78,76 +126,57 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig { private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5}; private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5}; - private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7}; + private final Register[] fpuFloatParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7}; private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null}; + // @formatter:off - private final Register[] callerSaveRegisters = - {g1, g2, g3, g4, g5, g6, g7, - o0, o1, o2, o3, o4, o5, o7, - f0, f1, f2, f3, f4, f5, f6, f7, - f8, f9, f10, f11, f12, f13, f14, f15, - f16, f17, f18, f19, f20, f21, f22, f23, - f24, f25, f26, f27, f28, f29, f30, f31, - d32, d34, d36, d38, d40, d42, d44, d46, - d48, d50, d52, d54, d56, d58, d60, d62}; - // @formatter:on + private final Register[] callerSaveRegisters; /** * Registers saved by the callee. This lists all L and I registers which are saved in the * register window. */ - private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, i6, i7}; + private final Register[] calleeSaveRegisters = { + l0, l1, l2, l3, l4, l5, l6, l7, + i0, i1, i2, i3, i4, i5, i6, i7}; + // @formatter:on - private static Register[] initAllocatable(boolean reserveForHeapBase) { - Register[] registers = null; - if (reserveForHeapBase) { - // @formatter:off - registers = new Register[]{ - // TODO this is not complete - // o7 cannot be used as register because it is always overwritten on call - // and the current register handler would ignore this fact if the called - // method still does not modify registers, in fact o7 is modified by the Call instruction - // There would be some extra handlin necessary to be able to handle the o7 properly for local usage - g1, g4, g5, - o0, o1, o2, o3, o4, o5, /*o6,o7,*/ - l0, l1, l2, l3, l4, l5, l6, l7, - i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/ - //f0, f1, f2, f3, f4, f5, f6, f7, - f8, f9, f10, f11, f12, f13, f14, f15, - f16, f17, f18, f19, f20, f21, f22, f23, - f24, f25, f26, f27, f28, f29, f30, f31, - d32, d34, d36, d38, d40, d42, d44, d46, - d48, d50, d52, d54, d56, d58, d60, d62 - }; - // @formatter:on - } else { - // @formatter:off - registers = new Register[]{ - // TODO this is not complete - g1, g4, g5, - o0, o1, o2, o3, o4, o5, /*o6, o7,*/ - l0, l1, l2, l3, l4, l5, l6, l7, - i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/ -// f0, f1, f2, f3, f4, f5, f6, f7 - f8, f9, f10, f11, f12, f13, f14, f15, - f16, f17, f18, f19, f20, f21, f22, f23, - f24, f25, f26, f27, f28, f29, f30, f31, - d32, d34, d36, d38, d40, d42, d44, d46, - d48, d50, d52, d54, d56, d58, d60, d62 - }; - // @formatter:on + private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) { + Register[] allRegisters = arch.getAvailableValueRegisters(); + Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 4 : 3)]; + + int idx = 0; + for (Register reg : allRegisters) { + if (reg.equals(sp) || reg.equals(g2) || reg.equals(g0)) { + // skip g0, stack pointer and thread register + continue; + } + if (reserveForHeapBase && reg.equals(g6)) { + // skip heap base register + continue; + } + + registers[idx++] = reg; } + assert idx == registers.length; return registers; } - public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) { - this(target, initAllocatable(config.useCompressedOops)); + public SPARCHotSpotRegisterConfig(Architecture arch, HotSpotVMConfig config) { + this(arch, initAllocatable(arch, config.useCompressedOops), config); } - public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) { - this.architecture = target.arch; + public SPARCHotSpotRegisterConfig(Architecture arch, Register[] allocatable, HotSpotVMConfig config) { + this.architecture = arch; this.allocatable = allocatable.clone(); + this.addNativeRegisterArgumentSlots = config.linuxOs; + HashSet callerSaveSet = new HashSet<>(); + Collections.addAll(callerSaveSet, arch.getAvailableValueRegisters()); + for (Register cs : calleeSaveRegisters) { + callerSaveSet.remove(cs); + } + this.callerSaveRegisters = callerSaveSet.toArray(new Register[callerSaveSet.size()]); attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters); } @@ -172,21 +201,31 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig { @Override public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { - if (type == Type.JavaCall || type == Type.NativeCall) { + if (type == JavaCall || type == NativeCall) { return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly); } - if (type == Type.JavaCallee) { + if (type == JavaCallee) { return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly); } throw JVMCIError.shouldNotReachHere(); } public Register[] getCallingConventionRegisters(Type type, JavaKind kind) { - if (architecture.canStoreValue(FPUs, kind) || architecture.canStoreValue(FPUd, kind)) { - return fpuParameterRegisters; + switch (kind) { + case Boolean: + case Byte: + case Short: + case Char: + case Int: + case Long: + case Object: + return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters; + case Double: + case Float: + return fpuFloatParameterRegisters; + default: + throw JVMCIError.shouldNotReachHere("Unknown JavaKind " + kind); } - assert architecture.canStoreValue(CPU, kind); - return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters; } private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) { @@ -213,7 +252,7 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig { } break; case Double: - if (!stackOnly && currentFloating < fpuParameterRegisters.length) { + if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) { if (currentFloating % 2 != 0) { // Make register number even to be a double reg currentFloating++; @@ -224,8 +263,8 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig { } break; case Float: - if (!stackOnly && currentFloating < fpuParameterRegisters.length) { - Register register = fpuParameterRegisters[currentFloating++]; + if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) { + Register register = fpuFloatParameterRegisters[currentFloating++]; locations[i] = register.asValue(target.getLIRKind(kind)); } break; @@ -234,20 +273,27 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig { } if (locations[i] == null) { + LIRKind lirKind = target.getLIRKind(kind); // Stack slot is always aligned to its size in bytes but minimum wordsize - int typeSize = SPARC.spillSlotSize(target, kind); + int typeSize = lirKind.getPlatformKind().getSizeInBytes(); currentStackOffset = roundUp(currentStackOffset, typeSize); - int slotOffset = currentStackOffset + SPARC.REGISTER_SAFE_AREA_SIZE; - locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), slotOffset, !type.out); + int slotOffset = currentStackOffset + REGISTER_SAFE_AREA_SIZE; + locations[i] = StackSlot.get(lirKind, slotOffset, !type.out); currentStackOffset += typeSize; } } - JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind(); - AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind())); - // Space where callee may spill outgoing parameters o0...o5 - int lowerOutgoingSpace = Math.min(locations.length, 6) * target.wordSize; - return new CallingConvention(currentStackOffset + lowerOutgoingSpace, returnLocation, locations); + JavaKind returnKind = returnType == null ? Void : returnType.getJavaKind(); + AllocatableValue returnLocation = returnKind == Void ? ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind())); + + int outArgSpillArea; + if (type == NativeCall && addNativeRegisterArgumentSlots) { + // Space for native callee which may spill our outgoing arguments + outArgSpillArea = Math.min(locations.length, generalParameterRegisters.length) * target.wordSize; + } else { + outArgSpillArea = 0; + } + return new CallingConvention(currentStackOffset + outArgSpillArea, returnLocation, locations); } private static int roundUp(int number, int mod) { @@ -256,7 +302,7 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig { @Override public Register getReturnRegister(JavaKind kind) { - return getReturnRegister(kind, Type.JavaCallee); + return getReturnRegister(kind, JavaCallee); } private static Register getReturnRegister(JavaKind kind, Type type) { @@ -268,7 +314,7 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig { case Int: case Long: case Object: - return type == Type.JavaCallee ? i0 : o0; + return type == JavaCallee ? i0 : o0; case Float: return f0; case Double: diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index 1e96b96d7c1..536c93af36e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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,6 +23,7 @@ package jdk.vm.ci.hotspot; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import static jdk.vm.ci.inittimer.InitTimer.timer; import java.lang.reflect.Constructor; @@ -36,7 +37,6 @@ import jdk.vm.ci.inittimer.InitTimer; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.SpeculationLog; import sun.misc.Unsafe; /** @@ -44,7 +44,7 @@ import sun.misc.Unsafe; * pointer as an argument (e.g., {@link #getSymbol(long)}) is undefined if the argument does not * denote a valid native object. */ -public final class CompilerToVM { +final class CompilerToVM { /** * Initializes the native part of the JVMCI runtime. */ @@ -61,6 +61,14 @@ public final class CompilerToVM { } } + /** + * Gets the {@link CompilerToVM} instance associated with the singleton + * {@link HotSpotJVMCIRuntime} instance. + */ + public static CompilerToVM compilerToVM() { + return runtime().getCompilerToVM(); + } + /** * Copies the original bytecode of {@code method} into a new byte array and returns it. * @@ -301,7 +309,7 @@ public final class CompilerToVM { * {@link HotSpotVMConfig#codeInstallResultDependenciesFailed} or * {@link HotSpotVMConfig#codeInstallResultDependenciesInvalid}. */ - public native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog); + native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, HotSpotSpeculationLog speculationLog); public native int getMetadata(TargetDescription target, HotSpotCompiledCode compiledCode, HotSpotMetaData metaData); @@ -317,18 +325,18 @@ public final class CompilerToVM { * @param timeUnitsPerSecond the granularity of the units for the {@code time} value * @param installedCode the nmethod installed as a result of the compilation */ - public synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethodImpl method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, + synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethodImpl method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode); /** * Resets all compilation statistics. */ - public native void resetCompilationStatistics(); + native void resetCompilationStatistics(); /** * Initializes the fields of {@code config}. */ - native long initializeConfiguration(); + native long initializeConfiguration(HotSpotVMConfig config); /** * Resolves the implementation of {@code method} for virtual dispatches on objects of dynamic @@ -367,7 +375,7 @@ public final class CompilerToVM { * @param address an address that may be called from any code in the code cache * @return -1 if {@code address == 0} */ - public native long getMaxCallTargetOffset(long address); + native long getMaxCallTargetOffset(long address); /** * Gets a textual disassembly of {@code codeBlob}. @@ -376,7 +384,7 @@ public final class CompilerToVM { * {@code codeBlob} could not be disassembled for some reason */ // The HotSpot disassembler seems not to be thread safe so it's better to synchronize its usage - public synchronized native String disassembleCodeBlob(long codeBlob); + synchronized native String disassembleCodeBlob(InstalledCode installedCode); /** * Gets a stack trace element for {@code method} at bytecode index {@code bci}. @@ -454,12 +462,12 @@ public final class CompilerToVM { * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be * raised the next time {@code installedCode} is executed. */ - public native void invalidateInstalledCode(InstalledCode installedCode); + native void invalidateInstalledCode(InstalledCode installedCode); /** * Collects the current values of all JVMCI benchmark counters, summed up over all threads. */ - public native long[] collectCounters(); + native long[] collectCounters(); /** * Determines if {@code metaspaceMethodData} is mature. @@ -489,7 +497,7 @@ public final class CompilerToVM { * @param methods the methods to look for, where {@code null} means that any frame is returned * @return the frame, or {@code null} if the end of the stack was reached during the search */ - public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethodImpl[] methods, int initialSkip); + native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, ResolvedJavaMethod[] methods, int initialSkip); /** * Materializes all virtual objects within {@code stackFrame} updates its locals. @@ -512,30 +520,34 @@ public final class CompilerToVM { /** * Determines if debug info should also be emitted at non-safepoint locations. */ - public native boolean shouldDebugNonSafepoints(); + + native boolean shouldDebugNonSafepoints(); /** * Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to the * HotSpot's log stream. * - * @exception NullPointerException if bytes is null. + * @exception NullPointerException if {@code bytes == null} * @exception IndexOutOfBoundsException if copying would cause access of data outside array - * bounds. + * bounds */ - public native void writeDebugOutput(byte[] bytes, int offset, int length); + native void writeDebugOutput(byte[] bytes, int offset, int length); /** * Flush HotSpot's log stream. */ - public native void flushDebugOutput(); + native void flushDebugOutput(); /** - * Read a value representing a metaspace Method* and return the - * {@link HotSpotResolvedJavaMethodImpl} wrapping it. This method does no checking that the - * location actually contains a valid Method*. If the {@code base} object is a + * Read a HotSpot Method* value from the memory location described by {@code base} plus + * {@code displacement} and return the {@link HotSpotResolvedJavaMethodImpl} wrapping it. This + * method does no checking that the memory location actually contains a valid pointer and may + * crash the VM if an invalid location is provided. If the {@code base} is null then + * {@code displacement} is used by itself. If {@code base} is a * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object - * and used as the base. Otherwise the object itself is used as the base. + * and added to {@code displacement}. Any other non-null object type causes an + * {@link IllegalArgumentException} to be thrown. * * @param base an object to read from or null * @param displacement @@ -544,12 +556,14 @@ public final class CompilerToVM { native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base, long displacement); /** - * Read a value representing a metaspace ConstantPool* and return the - * {@link HotSpotConstantPool} wrapping it. This method does no checking that the location - * actually contains a valid ConstantPool*. If the {@code base} object is a - * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or - * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object - * and used as the base. Otherwise the object itself is used as the base. + * Read a HotSpot ConstantPool* value from the memory location described by {@code base} plus + * {@code displacement} and return the {@link HotSpotConstantPool} wrapping it. This method does + * no checking that the memory location actually contains a valid pointer and may crash the VM + * if an invalid location is provided. If the {@code base} is null then {@code displacement} is + * used by itself. If {@code base} is a {@link HotSpotResolvedJavaMethodImpl}, + * {@link HotSpotConstantPool} or {@link HotSpotResolvedObjectTypeImpl} then the metaspace + * pointer is fetched from that object and added to {@code displacement}. Any other non-null + * object type causes an {@link IllegalArgumentException} to be thrown. * * @param base an object to read from or null * @param displacement @@ -558,12 +572,15 @@ public final class CompilerToVM { native HotSpotConstantPool getConstantPool(Object base, long displacement); /** - * Read a value representing a metaspace Klass* and return the - * {@link HotSpotResolvedObjectTypeImpl} wrapping it. The method does no checking that the - * location actually contains a valid Klass*. If the {@code base} object is a + * Read a HotSpot Klass* value from the memory location described by {@code base} plus + * {@code displacement} and return the {@link HotSpotResolvedObjectTypeImpl} wrapping it. This + * method does no checking that the memory location actually contains a valid pointer and may + * crash the VM if an invalid location is provided. If the {@code base} is null then + * {@code displacement} is used by itself. If {@code base} is a * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object - * and used as the base. Otherwise the object itself is used as the base. + * and added to {@code displacement}. Any other non-null object type causes an + * {@link IllegalArgumentException} to be thrown. * * @param base an object to read from or null * @param displacement @@ -571,4 +588,17 @@ public final class CompilerToVM { * @return null or the resolved method for this location */ native HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement, boolean compressed); + + /** + * Return the size of the HotSpot ProfileData* pointed at by {@code position}. If + * {@code position} is outside the space of the MethodData then an + * {@link IllegalArgumentException} is thrown. A {@code position} inside the MethodData but that + * isn't pointing at a valid ProfileData will crash the VM. + * + * @param metaspaceMethodData + * @param position + * @return the size of the ProfileData item pointed at by {@code position} + * @throws IllegalArgumentException if an out of range position is given + */ + native int methodDataProfileDataSize(long metaspaceMethodData, int position); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java index b1ccd16d14d..6f9770a5c2d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java @@ -22,15 +22,30 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotCompressedNullConstant.*; +import static jdk.vm.ci.hotspot.HotSpotCompressedNullConstant.COMPRESSED_NULL; -import java.lang.reflect.*; +import java.lang.reflect.Field; -import jdk.vm.ci.code.*; -import jdk.vm.ci.code.CompilationResult.*; -import jdk.vm.ci.code.DataSection.*; -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.code.CodeCacheProvider; +import jdk.vm.ci.code.CompilationRequest; +import jdk.vm.ci.code.CompilationResult; +import jdk.vm.ci.code.CompilationResult.Call; +import jdk.vm.ci.code.CompilationResult.ConstantReference; +import jdk.vm.ci.code.CompilationResult.DataPatch; +import jdk.vm.ci.code.CompilationResult.Mark; +import jdk.vm.ci.code.DataSection; +import jdk.vm.ci.code.DataSection.Data; +import jdk.vm.ci.code.DataSection.DataBuilder; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.SerializableConstant; +import jdk.vm.ci.meta.SpeculationLog; +import jdk.vm.ci.meta.VMConstant; /** * HotSpot implementation of {@link CodeCacheProvider}. @@ -98,72 +113,64 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider { return runtime.getConfig().runtimeCallStackSize; } - public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) { - HotSpotJVMCIRuntime.runtime().notifyInstall(this, installedCode, compResult); + private InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) { + ((HotSpotJVMCIRuntime) runtime).notifyInstall(this, installedCode, compResult); return installedCode; } - private InstalledCode installCode(CompilationResult compResult, HotSpotCompiledNmethod compiledCode, InstalledCode installedCode, SpeculationLog log) { - int result = runtime.getCompilerToVM().installCode(target, compiledCode, installedCode, log); - if (result != config.codeInstallResultOk) { - String msg = compiledCode.getInstallationFailureMessage(); - String resultDesc = config.getCodeInstallResultDescription(result); - if (msg != null) { - msg = String.format("Code installation failed: %s%n%s", resultDesc, msg); - } else { - msg = String.format("Code installation failed: %s", resultDesc); - } - if (result == config.codeInstallResultDependenciesInvalid) { - throw new AssertionError(resultDesc + " " + msg); - } - throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg); - } - return logOrDump(installedCode, compResult); - } - - public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long jvmciEnv, boolean isDefault) { - if (compResult.getId() == -1) { - compResult.setId(method.allocateCompileId(compResult.getEntryBCI())); - } - HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), isDefault); - HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(method, compResult, jvmciEnv); - return installCode(compResult, compiledCode, installedCode, method.getSpeculationLog()); - } - - @Override - public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) { - HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; - if (compResult.getId() == -1) { - compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI())); - } - InstalledCode installedCode = predefinedInstalledCode; + public InstalledCode installCode(CompilationRequest compRequest, CompilationResult compResult, InstalledCode installedCode, SpeculationLog log, boolean isDefault) { + HotSpotResolvedJavaMethod method = compRequest != null ? (HotSpotResolvedJavaMethod) compRequest.getMethod() : null; + InstalledCode resultInstalledCode; if (installedCode == null) { - HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false); - installedCode = code; + if (method == null) { + // Must be a stub + resultInstalledCode = new HotSpotRuntimeStub(compResult.getName()); + } else { + resultInstalledCode = new HotSpotNmethod(method, compResult.getName(), isDefault); + } + } else { + resultInstalledCode = installedCode; } - HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult); - return installCode(compResult, compiledCode, installedCode, log); + HotSpotCompiledCode compiledCode; + if (method != null) { + final int id; + final long jvmciEnv; + if (compRequest instanceof HotSpotCompilationRequest) { + HotSpotCompilationRequest hsCompRequest = (HotSpotCompilationRequest) compRequest; + id = hsCompRequest.getId(); + jvmciEnv = hsCompRequest.getJvmciEnv(); + } else { + id = method.allocateCompileId(compRequest.getEntryBCI()); + jvmciEnv = 0L; + } + compiledCode = new HotSpotCompiledNmethod(method, compResult, id, jvmciEnv); + } else { + compiledCode = new HotSpotCompiledCode(compResult); + } + int result = runtime.getCompilerToVM().installCode(target, compiledCode, resultInstalledCode, (HotSpotSpeculationLog) log); + if (result != config.codeInstallResultOk) { + String resultDesc = config.getCodeInstallResultDescription(result); + if (compiledCode instanceof HotSpotCompiledNmethod) { + HotSpotCompiledNmethod compiledNmethod = (HotSpotCompiledNmethod) compiledCode; + String msg = compiledNmethod.getInstallationFailureMessage(); + if (msg != null) { + msg = String.format("Code installation failed: %s%n%s", resultDesc, msg); + } else { + msg = String.format("Code installation failed: %s", resultDesc); + } + if (result == config.codeInstallResultDependenciesInvalid) { + throw new AssertionError(resultDesc + " " + msg); + } + throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg); + } else { + throw new BailoutException("Error installing %s: %s", compResult.getName(), resultDesc); + } + } + return logOrDump(resultInstalledCode, compResult); } - @Override - public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) { - HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; - return installMethod(hotspotMethod, compResult, 0L, true); - } - - public HotSpotNmethod addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) { - HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method; - if (compResult.getId() == -1) { - compResult.setId(javaMethod.allocateCompileId(compResult.getEntryBCI())); - } - HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true); - HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(javaMethod, compResult); - CompilerToVM vm = runtime.getCompilerToVM(); - int result = vm.installCode(target, compiled, code, null); - if (result != runtime.getConfig().codeInstallResultOk) { - return null; - } - return code; + public void invalidateInstalledCode(InstalledCode installedCode) { + runtime.getCompilerToVM().invalidateInstalledCode(installedCode); } public boolean needsDataPatch(JavaConstant constant) { @@ -176,35 +183,29 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider { if (constant instanceof VMConstant) { VMConstant vmConstant = (VMConstant) constant; boolean compressed; - long raw; - if (constant instanceof HotSpotObjectConstant) { - HotSpotObjectConstant c = (HotSpotObjectConstant) vmConstant; + if (constant instanceof HotSpotConstant) { + HotSpotConstant c = (HotSpotConstant) vmConstant; compressed = c.isCompressed(); - raw = 0xDEADDEADDEADDEADL; - } else if (constant instanceof HotSpotMetaspaceConstant) { - HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) constant; - compressed = meta.isCompressed(); - raw = meta.rawValue(); } else { throw new JVMCIError(String.valueOf(constant)); } - size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind); + size = compressed ? 4 : target.wordSize; if (size == 4) { builder = (buffer, patch) -> { patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant))); - buffer.putInt((int) raw); + buffer.putInt(0xDEADDEAD); }; } else { assert size == 8; builder = (buffer, patch) -> { patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant))); - buffer.putLong(raw); + buffer.putLong(0xDEADDEADDEADDEADL); }; } } else if (JavaConstant.isNull(constant)) { boolean compressed = COMPRESSED_NULL.equals(constant); - size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind); + size = compressed ? 4 : target.wordSize; builder = DataBuilder.zero(size); } else if (constant instanceof SerializableConstant) { SerializableConstant s = (SerializableConstant) constant; @@ -250,8 +251,7 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider { public String disassemble(InstalledCode code) { if (code.isValid()) { - long codeBlob = code.getAddress(); - return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob); + return runtime.getCompilerToVM().disassembleCodeBlob(code); } return null; } @@ -259,4 +259,35 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider { public SpeculationLog createSpeculationLog() { return new HotSpotSpeculationLog(); } + + public long getMaxCallTargetOffset(long address) { + return runtime.getCompilerToVM().getMaxCallTargetOffset(address); + } + + public boolean shouldDebugNonSafepoints() { + return runtime.getCompilerToVM().shouldDebugNonSafepoints(); + } + + /** + * Notifies the VM of statistics for a completed compilation. + * + * @param id the identifier of the compilation + * @param method the method compiled + * @param osr specifies if the compilation was for on-stack-replacement + * @param processedBytecodes the number of bytecodes processed during the compilation, including + * the bytecodes of all inlined methods + * @param time the amount time spent compiling {@code method} + * @param timeUnitsPerSecond the granularity of the units for the {@code time} value + * @param installedCode the nmethod installed as a result of the compilation + */ + public void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode) { + runtime.getCompilerToVM().notifyCompilationStatistics(id, (HotSpotResolvedJavaMethodImpl) method, osr, processedBytecodes, time, timeUnitsPerSecond, installedCode); + } + + /** + * Resets all compilation statistics. + */ + public void resetCompilationStatistics() { + runtime.getCompilerToVM().resetCompilationStatistics(); + } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java new file mode 100644 index 00000000000..dee71da6167 --- /dev/null +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015, 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.vm.ci.hotspot; + +import jdk.vm.ci.code.CompilationRequest; + +/** + * A compilation request with extra HotSpot specific context such as a compilation identifier and + * the address of a {@code JVMCIEnv} object that provides native context for a compilation. + */ +public class HotSpotCompilationRequest extends CompilationRequest { + private final long jvmciEnv; + private final int id; + + /** + * Creates a request to compile a method starting at a given BCI and allocates an identifier to + * the request. + * + * @param method the method to be compiled + * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the + * method's entry point + * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L + */ + public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv) { + this(method, entryBCI, jvmciEnv, method.allocateCompileId(entryBCI)); + } + + /** + * Creates a request to compile a method starting at a given BCI. + * + * @param method the method to be compiled + * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the + * method's entry point + * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L + * @param id an identifier for the request + */ + public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) { + super(method, entryBCI); + this.jvmciEnv = jvmciEnv; + this.id = id; + } + + @Override + public HotSpotResolvedJavaMethod getMethod() { + return (HotSpotResolvedJavaMethod) super.getMethod(); + } + + /** + * Gets the address of the native {@code JVMCIEnv} object or 0L if no such object exists. + */ + public long getJvmciEnv() { + return jvmciEnv; + } + + /** + * Gets the VM allocated identifier for this compilation. + */ + public int getId() { + return id; + } + +} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java index c70c46f2fbf..a2ec65fbafc 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java @@ -22,12 +22,16 @@ */ package jdk.vm.ci.hotspot; -import java.nio.*; -import java.util.*; -import java.util.stream.*; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Stream; import java.util.stream.Stream.Builder; -import jdk.vm.ci.code.*; +import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.code.CompilationResult; import jdk.vm.ci.code.CompilationResult.CodeAnnotation; import jdk.vm.ci.code.CompilationResult.CodeComment; import jdk.vm.ci.code.CompilationResult.DataPatch; @@ -36,14 +40,15 @@ import jdk.vm.ci.code.CompilationResult.Infopoint; import jdk.vm.ci.code.CompilationResult.JumpTable; import jdk.vm.ci.code.CompilationResult.Mark; import jdk.vm.ci.code.CompilationResult.Site; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.DataSection; import jdk.vm.ci.meta.Assumptions.Assumption; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * A {@link CompilationResult} with additional HotSpot-specific information required for installing * the code in HotSpot's code cache. */ -public abstract class HotSpotCompiledCode { +public class HotSpotCompiledCode { public final String name; public final Site[] sites; @@ -113,9 +118,7 @@ public abstract class HotSpotCompiledCode { targetCodeSize = compResult.getTargetCodeSize(); DataSection data = compResult.getDataSection(); - if (!data.isFinalized()) { - data.finalizeLayout(); - } + data.finalizeLayout(); dataSection = new byte[data.getSectionSize()]; ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder()); @@ -176,4 +179,9 @@ public abstract class HotSpotCompiledCode { Arrays.sort(result, new SiteComparator()); return result; } + + @Override + public String toString() { + return name; + } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java index b23aec07823..e81f35b5e43 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java @@ -22,8 +22,8 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.code.*; -import jdk.vm.ci.inittimer.*; +import jdk.vm.ci.code.CompilationResult; +import jdk.vm.ci.inittimer.SuppressFBWarnings; /** * {@link HotSpotCompiledCode} destined for installation as an nmethod. @@ -32,8 +32,17 @@ public final class HotSpotCompiledNmethod extends HotSpotCompiledCode { public final HotSpotResolvedJavaMethod method; public final int entryBCI; + + /** + * Compilation identifier. + */ public final int id; + + /** + * Address of a native {@code JVMCIEnv} object or 0L if no such object exists. + */ public final long jvmciEnv; + public final boolean hasUnsafeAccess; /** @@ -42,15 +51,11 @@ public final class HotSpotCompiledNmethod extends HotSpotCompiledCode { */ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "set by the VM") private String installationFailureMessage; - public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) { - this(method, compResult, 0L); - } - - public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long jvmciEnv) { + public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, int id, long jvmciEnv) { super(compResult); this.method = method; this.entryBCI = compResult.getEntryBCI(); - this.id = compResult.getId(); + this.id = id; this.jvmciEnv = jvmciEnv; this.hasUnsafeAccess = compResult.hasUnsafeAccess(); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompressedNullConstant.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompressedNullConstant.java index 228848c997f..7243305606d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompressedNullConstant.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompressedNullConstant.java @@ -22,7 +22,9 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; /** * The compressed representation of the {@link JavaConstant#NULL_POINTER null constant}. @@ -48,6 +50,14 @@ public final class HotSpotCompressedNullConstant implements JavaConstant, HotSpo return true; } + public Constant compress() { + throw new IllegalArgumentException(); + } + + public Constant uncompress() { + return NULL_POINTER; + } + @Override public boolean isDefaultForKind() { return true; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstant.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstant.java index 55544367808..ee4cb7bb397 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstant.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstant.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.Constant; /** * Marker interface for hotspot specific constants. @@ -30,4 +30,8 @@ import jdk.vm.ci.meta.*; public interface HotSpotConstant extends Constant { boolean isCompressed(); + + Constant compress(); + + Constant uncompress(); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java index cae64abaa8d..0885a2dcded 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java @@ -22,18 +22,27 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*; +import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; -import java.lang.invoke.*; +import java.lang.invoke.MethodHandle; -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaField; +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; /** * Implementation of {@link ConstantPool} for HotSpot. */ -public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified, MetaspaceWrapperObject { +final class HotSpotConstantPool implements ConstantPool, HotSpotProxified, MetaspaceWrapperObject { /** * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}. @@ -121,10 +130,6 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified this.tag = tag; } - private static HotSpotVMConfig config() { - return runtime().getConfig(); - } - /** * Maps JVM_CONSTANT tags to {@link JVM_CONSTANT} values. Using a separate class for lazy * initialization. @@ -204,7 +209,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified * @return holder for this constant pool */ private HotSpotResolvedObjectType getHolder() { - return runtime().getCompilerToVM().getResolvedJavaType(this, runtime().getConfig().constantPoolHolderOffset, false); + return compilerToVM().getResolvedJavaType(this, config().constantPoolHolderOffset, false); } /** @@ -224,7 +229,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified } else { assert opcode == Bytecodes.GETFIELD || opcode == Bytecodes.PUTFIELD || opcode == Bytecodes.GETSTATIC || opcode == Bytecodes.PUTSTATIC || opcode == Bytecodes.INVOKEINTERFACE || opcode == Bytecodes.INVOKEVIRTUAL || opcode == Bytecodes.INVOKESPECIAL || opcode == Bytecodes.INVOKESTATIC : "unexpected invoke opcode " + opcode; - index = rawIndex + runtime().getConfig().constantPoolCpCacheIndexTag; + index = rawIndex + config().constantPoolCpCacheIndexTag; } return index; } @@ -241,7 +246,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified if (isInvokedynamicIndex(index)) { return decodeInvokedynamicIndex(index); } else { - return index - runtime().getConfig().constantPoolCpCacheIndexTag; + return index - config().constantPoolCpCacheIndexTag; } } @@ -260,7 +265,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified return ~i; } - public long getMetaspaceConstantPool() { + long getMetaspaceConstantPool() { return metaspaceConstantPool; } @@ -276,7 +281,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified */ private JVM_CONSTANT getTagAt(int index) { assertBounds(index); - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); final long metaspaceConstantPoolTags = UNSAFE.getAddress(getMetaspaceConstantPool() + config.constantPoolTagsOffset); final int tag = UNSAFE.getByteVolatile(null, metaspaceConstantPoolTags + config.arrayU1DataOffset + index); if (tag == 0) { @@ -293,7 +298,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified */ private long getEntryAt(int index) { assertBounds(index); - return UNSAFE.getAddress(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); + return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); } /** @@ -304,7 +309,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified */ private int getIntAt(int index) { assertTag(index, JVM_CONSTANT.Integer); - return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); + return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); } /** @@ -315,7 +320,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified */ private long getLongAt(int index) { assertTag(index, JVM_CONSTANT.Long); - return UNSAFE.getLong(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); + return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); } /** @@ -326,7 +331,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified */ private float getFloatAt(int index) { assertTag(index, JVM_CONSTANT.Float); - return UNSAFE.getFloat(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); + return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); } /** @@ -337,7 +342,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified */ private double getDoubleAt(int index) { assertTag(index, JVM_CONSTANT.Double); - return UNSAFE.getDouble(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); + return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); } /** @@ -348,7 +353,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified */ private int getNameAndTypeAt(int index) { assertTag(index, JVM_CONSTANT.NameAndType); - return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); + return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); } /** @@ -359,7 +364,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified * @return {@code JVM_CONSTANT_NameAndType} reference constant pool entry */ private int getNameAndTypeRefIndexAt(int index) { - return runtime().getCompilerToVM().lookupNameAndTypeRefIndexInPool(this, index); + return compilerToVM().lookupNameAndTypeRefIndexInPool(this, index); } /** @@ -370,7 +375,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified * @return name as {@link String} */ private String getNameOf(int which) { - return runtime().getCompilerToVM().lookupNameInPool(this, which); + return compilerToVM().lookupNameInPool(this, which); } /** @@ -394,7 +399,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified * @return signature as {@link String} */ private String getSignatureOf(int which) { - return runtime().getCompilerToVM().lookupSignatureInPool(this, which); + return compilerToVM().lookupSignatureInPool(this, which); } /** @@ -417,7 +422,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified * @return klass reference index */ private int getKlassRefIndexAt(int index) { - return runtime().getCompilerToVM().lookupKlassRefIndexInPool(this, index); + return compilerToVM().lookupKlassRefIndexInPool(this, index); } /** @@ -427,22 +432,11 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified * @param index constant pool index * @return klass reference index */ - private int getUncachedKlassRefIndexAt(int index, JVM_CONSTANT tag) { - int resultIndex; - if (tag == JVM_CONSTANT.MethodRef || tag == JVM_CONSTANT.Fieldref || tag == JVM_CONSTANT.InterfaceMethodref) { - assertTagIsFieldOrMethod(index); - final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); - // klass ref index is in the low 16-bits. - resultIndex = refIndex & 0xFFFF; - } else { - resultIndex = index; - } - - // Read the tag only once because it could change between multiple reads. - final JVM_CONSTANT klassTag = getTagAt(resultIndex); - assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag; - - return resultIndex; + private int getUncachedKlassRefIndexAt(int index) { + assertTagIsFieldOrMethod(index); + final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); + // klass ref index is in the low 16-bits. + return refIndex & 0xFFFF; } /** @@ -478,7 +472,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified @Override public int length() { - return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolLengthOffset); + return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolLengthOffset); } @Override @@ -505,13 +499,13 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified * "pseudo strings" (arbitrary live objects) patched into a String entry. Such * entries do not have a symbol in the constant pool slot. */ - Object string = runtime().getCompilerToVM().resolvePossiblyCachedConstantInPool(this, cpi); + Object string = compilerToVM().resolvePossiblyCachedConstantInPool(this, cpi); return HotSpotObjectConstantImpl.forObject(string); case MethodHandle: case MethodHandleInError: case MethodType: case MethodTypeInError: - Object obj = runtime().getCompilerToVM().resolveConstantInPool(this, cpi); + Object obj = compilerToVM().resolveConstantInPool(this, cpi); return HotSpotObjectConstantImpl.forObject(obj); default: throw new JVMCIError("Unknown constant pool tag %s", tag); @@ -521,7 +515,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified @Override public String lookupUtf8(int cpi) { assertTag(cpi, JVM_CONSTANT.Utf8); - return runtime().getCompilerToVM().getSymbol(getEntryAt(cpi)); + return compilerToVM().getSymbol(getEntryAt(cpi)); } @Override @@ -533,7 +527,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified public JavaConstant lookupAppendix(int cpi, int opcode) { assert Bytecodes.isInvoke(opcode); final int index = rawIndexToConstantPoolIndex(cpi, opcode); - Object appendix = runtime().getCompilerToVM().lookupAppendixInPool(this, index); + Object appendix = compilerToVM().lookupAppendixInPool(this, index); if (appendix == null) { return null; } else { @@ -558,7 +552,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified @Override public JavaMethod lookupMethod(int cpi, int opcode) { final int index = rawIndexToConstantPoolIndex(cpi, opcode); - final HotSpotResolvedJavaMethod method = runtime().getCompilerToVM().lookupMethodInPool(this, index, (byte) opcode); + final HotSpotResolvedJavaMethod method = compilerToVM().lookupMethodInPool(this, index, (byte) opcode); if (method != null) { return method; } else { @@ -570,7 +564,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified return new HotSpotMethodUnresolved(name, signature, holder); } else { final int klassIndex = getKlassRefIndexAt(index); - final Object type = runtime().getCompilerToVM().lookupKlassInPool(this, klassIndex); + final Object type = compilerToVM().lookupKlassInPool(this, klassIndex); JavaType holder = getJavaType(type); return new HotSpotMethodUnresolved(name, signature, holder); } @@ -583,7 +577,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified if (elem != null && elem.lastCpi == cpi) { return elem.javaType; } else { - final Object type = runtime().getCompilerToVM().lookupKlassInPool(this, cpi); + final Object type = compilerToVM().lookupKlassInPool(this, cpi); JavaType result = getJavaType(type); if (result instanceof ResolvedJavaType) { this.lastLookupType = new LookupTypeCacheElement(cpi, result); @@ -609,7 +603,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified long[] info = new long[2]; HotSpotResolvedObjectTypeImpl resolvedHolder; try { - resolvedHolder = runtime().getCompilerToVM().resolveFieldInPool(this, index, (byte) opcode, info); + resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (byte) opcode, info); } catch (Throwable t) { /* * If there was an exception resolving the field we give up and return an unresolved @@ -643,8 +637,8 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified break; case Bytecodes.INVOKEDYNAMIC: { // invokedynamic instructions point to a constant pool cache entry. - index = decodeConstantPoolCacheIndex(cpi) + runtime().getConfig().constantPoolCpCacheIndexTag; - index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, index); + index = decodeConstantPoolCacheIndex(cpi) + config().constantPoolCpCacheIndexTag; + index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index); break; } case Bytecodes.GETSTATIC: @@ -657,7 +651,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified case Bytecodes.INVOKEINTERFACE: { // invoke and field instructions point to a constant pool cache entry. index = rawIndexToConstantPoolIndex(cpi, opcode); - index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, index); + index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index); break; } default: @@ -673,11 +667,15 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified case MethodRef: case Fieldref: case InterfaceMethodref: + index = getUncachedKlassRefIndexAt(index); + // Read the tag only once because it could change between multiple reads. + final JVM_CONSTANT klassTag = getTagAt(index); + assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag; + // fall through case Class: case UnresolvedClass: case UnresolvedClassInError: - index = getUncachedKlassRefIndexAt(index, tag); - final HotSpotResolvedObjectTypeImpl type = runtime().getCompilerToVM().resolveTypeInPool(this, index); + final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, index); Class klass = type.mirror(); if (!klass.isPrimitive() && !klass.isArray()) { UNSAFE.ensureClassInitialized(klass); @@ -687,14 +685,14 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified if (Bytecodes.isInvokeHandleAlias(opcode)) { final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode); if (isInvokeHandle(methodRefCacheIndex, type)) { - runtime().getCompilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex); + compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex); } } } break; case InvokeDynamic: if (isInvokedynamicIndex(cpi)) { - runtime().getCompilerToVM().resolveInvokeDynamicInPool(this, cpi); + compilerToVM().resolveInvokeDynamicInPool(this, cpi); } break; default: @@ -704,7 +702,7 @@ public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified } private boolean isInvokeHandle(int methodRefCacheIndex, HotSpotResolvedObjectTypeImpl klass) { - assertTag(runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef); + assertTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef); return ResolvedJavaMethod.isSignaturePolymorphic(klass, getNameOf(methodRefCacheIndex), runtime().getHostJVMCIBackend().getMetaAccess()); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java index 843176bae3d..a5d165feb61 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java @@ -22,12 +22,24 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider.Options.*; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; -import java.lang.reflect.*; +import java.lang.reflect.Array; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.options.*; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaField; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MemoryAccessProvider; +import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.options.Option; +import jdk.vm.ci.options.OptionType; +import jdk.vm.ci.options.OptionValue; +import jdk.vm.ci.options.StableOptionValue; /** * HotSpot implementation of {@link ConstantReflectionProvider}. @@ -60,11 +72,6 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv return memoryAccess; } - @Override - public boolean isEmbeddable(Constant constant) { - return true; - } - @Override public Boolean constantEquals(Constant x, Constant y) { if (x == y) { @@ -110,8 +117,8 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv } Class componentType = ((HotSpotObjectConstantImpl) array).object().getClass().getComponentType(); JavaKind kind = runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(componentType).getJavaKind(); - int arraybase = runtime.getArrayBaseOffset(kind); - int scale = runtime.getArrayIndexScale(kind); + int arraybase = getArrayBaseOffset(kind); + int scale = getArrayIndexScale(kind); if (offset < arraybase) { return -1; } @@ -207,6 +214,10 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv return HotSpotObjectConstantImpl.forObject(value); } + public JavaConstant forObject(Object value) { + return HotSpotObjectConstantImpl.forObject(value); + } + @Override public ResolvedJavaType asJavaType(Constant constant) { if (constant instanceof HotSpotObjectConstant) { @@ -216,7 +227,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv } } if (constant instanceof HotSpotMetaspaceConstant) { - Object obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant); + MetaspaceWrapperObject obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant); if (obj instanceof HotSpotResolvedObjectTypeImpl) { return (ResolvedJavaType) obj; } @@ -251,7 +262,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv * {@code value} was read */ protected boolean isFinalInstanceFieldValueConstant(JavaConstant value, Class receiverClass) { - return !value.isDefaultForKind() || TrustFinalDefaultFields.getValue(); + return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue(); } /** @@ -327,7 +338,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv if (!hotspotField.isStable()) { return readNonStableFieldValue(field, receiver); } else { - return readStableFieldValue(field, receiver, false); + return readStableFieldValue(field, receiver, hotspotField.isDefaultStable()); } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java index 00277ecd3f4..aa8368d9777 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java @@ -23,7 +23,6 @@ package jdk.vm.ci.hotspot; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; - import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.inittimer.SuppressFBWarnings; import sun.misc.Unsafe; @@ -59,18 +58,6 @@ public abstract class HotSpotInstalledCode extends InstalledCode { return size; } - /** - * @return a copy of this code blob if it is {@linkplain #isValid() valid}, null otherwise. - */ - public byte[] getBlob() { - if (!isValid()) { - return null; - } - byte[] blob = new byte[size]; - UNSAFE.copyMemory(null, getAddress(), blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size); - return blob; - } - @Override public abstract String toString(); @@ -79,7 +66,6 @@ public abstract class HotSpotInstalledCode extends InstalledCode { return codeStart; } - @Override public long getCodeSize() { return codeSize; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java index 50c51da78e9..1103fb73d98 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java @@ -22,12 +22,11 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.compiler.*; -import jdk.vm.ci.runtime.*; +import jdk.vm.ci.runtime.JVMCIBackend; public interface HotSpotJVMCIBackendFactory { - JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host); + JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host); /** * Gets the CPU architecture of this backend. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java index 1a0e5423165..1e242413b63 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -22,19 +22,18 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.code.*; -import jdk.vm.ci.common.*; -import jdk.vm.ci.compiler.*; -import jdk.vm.ci.compiler.Compiler; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.runtime.*; -import jdk.vm.ci.service.*; +import jdk.vm.ci.code.CompilationRequest; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.runtime.JVMCICompiler; +import jdk.vm.ci.runtime.JVMCICompilerFactory; +import jdk.vm.ci.runtime.JVMCIRuntime; +import jdk.vm.ci.service.Services; final class HotSpotJVMCICompilerConfig { - private static class DummyCompilerFactory implements CompilerFactory, Compiler { + private static class DummyCompilerFactory implements JVMCICompilerFactory, JVMCICompiler { - public void compileMethod(ResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) { + public void compileMethod(CompilationRequest request) { throw new JVMCIError("no JVMCI compiler selected"); } @@ -42,16 +41,12 @@ final class HotSpotJVMCICompilerConfig { return ""; } - public Architecture initializeArchitecture(Architecture arch) { - return arch; - } - - public Compiler createCompiler(JVMCIRuntime runtime) { + public JVMCICompiler createCompiler(JVMCIRuntime runtime) { return this; } } - private static CompilerFactory compilerFactory; + private static JVMCICompilerFactory compilerFactory; /** * Selects the system compiler. @@ -61,7 +56,7 @@ final class HotSpotJVMCICompilerConfig { */ static Boolean selectCompiler(String compilerName) { assert compilerFactory == null; - for (CompilerFactory factory : Services.load(CompilerFactory.class)) { + for (JVMCICompilerFactory factory : Services.load(JVMCICompilerFactory.class)) { if (factory.getCompilerName().equals(compilerName)) { compilerFactory = factory; return Boolean.TRUE; @@ -71,7 +66,7 @@ final class HotSpotJVMCICompilerConfig { throw new JVMCIError("JVMCI compiler '%s' not found", compilerName); } - static CompilerFactory getCompilerFactory() { + static JVMCICompilerFactory getCompilerFactory() { if (compilerFactory == null) { compilerFactory = new DummyCompilerFactory(); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java index b3bad532f7f..59299ea8516 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java @@ -22,10 +22,17 @@ */ package jdk.vm.ci.hotspot; -import java.lang.ref.*; -import java.util.*; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import java.util.WeakHashMap; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JVMCIMetaAccessContext; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaType; /** * This class manages the set of metadata roots that must be scanned during garbage collection. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 6b5204f5161..7ea4ebf407d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -22,54 +22,55 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.inittimer.InitTimer.*; +import static jdk.vm.ci.inittimer.InitTimer.timer; -import java.util.*; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; -import jdk.vm.ci.code.*; -import jdk.vm.ci.common.*; -import jdk.vm.ci.compiler.*; -import jdk.vm.ci.compiler.Compiler; -import jdk.vm.ci.inittimer.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.runtime.*; -import jdk.vm.ci.service.*; +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.CompilationResult; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.inittimer.InitTimer; +import jdk.vm.ci.meta.JVMCIMetaAccessContext; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.runtime.JVMCI; +import jdk.vm.ci.runtime.JVMCIBackend; +import jdk.vm.ci.runtime.JVMCICompiler; +import jdk.vm.ci.service.Services; //JaCoCo Exclude +/** + * HotSpot implementation of a JVMCI runtime. + * + * The initialization of this class is very fragile since it's initialized both through + * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and + * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class + * can't have a static initializer and any required initialization must be done as part of + * {@link #runtime()}. This allows the initialization to funnel back through + * {@link JVMCI#initialize()} without deadlocking. + */ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, HotSpotProxified { - /** - * The proper initialization of this class is complex because it's tangled up with the - * initialization of the JVMCI and really should only ever be triggered through - * {@link JVMCI#getRuntime}. However since {@link #runtime} can also be called directly it - * should also trigger proper initialization. To ensure proper ordering, the static initializer - * of this class initializes {@link JVMCI} and then access to {@link DelayedInit#instance} - * triggers the final initialization of the {@link HotSpotJVMCIRuntime}. - */ - static { - JVMCI.initialize(); - } - @SuppressWarnings("try") static class DelayedInit { private static final HotSpotJVMCIRuntime instance; static { - try (InitTimer t0 = timer("HotSpotJVMCIRuntime.")) { - try (InitTimer t = timer("StartupEventListener.beforeJVMCIStartup")) { - for (StartupEventListener l : Services.load(StartupEventListener.class)) { - l.beforeJVMCIStartup(); - } - } - - try (InitTimer t = timer("HotSpotJVMCIRuntime.")) { - instance = new HotSpotJVMCIRuntime(); - } - - try (InitTimer t = timer("HotSpotJVMCIRuntime.completeInitialization")) { - instance.completeInitialization(); - } + try (InitTimer t = timer("HotSpotJVMCIRuntime.")) { + instance = new HotSpotJVMCIRuntime(); } } } @@ -78,20 +79,10 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H * Gets the singleton {@link HotSpotJVMCIRuntime} object. */ public static HotSpotJVMCIRuntime runtime() { - assert DelayedInit.instance != null; + JVMCI.initialize(); return DelayedInit.instance; } - /** - * Do deferred initialization. - */ - public void completeInitialization() { - compiler = HotSpotJVMCICompilerConfig.getCompilerFactory().createCompiler(this); - for (HotSpotVMEventListener vmEventListener : vmEventListeners) { - vmEventListener.completeInitialization(this); - } - } - public static HotSpotJVMCIBackendFactory findFactory(String architecture) { for (HotSpotJVMCIBackendFactory factory : Services.load(HotSpotJVMCIBackendFactory.class)) { if (factory.getArchitecture().equalsIgnoreCase(architecture)) { @@ -106,7 +97,7 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend. */ public static JavaKind getHostWordKind() { - return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordKind; + return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind; } protected final CompilerToVM compilerToVm; @@ -114,16 +105,19 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H protected final HotSpotVMConfig config; private final JVMCIBackend hostBackend; - private Compiler compiler; + private volatile JVMCICompiler compiler; protected final JVMCIMetaAccessContext metaAccessContext; private final Map, JVMCIBackend> backends = new HashMap<>(); private final Iterable vmEventListeners; + @SuppressWarnings("unused") private final String[] trivialPrefixes; + @SuppressWarnings("try") private HotSpotJVMCIRuntime() { compilerToVm = new CompilerToVM(); + try (InitTimer t = timer("HotSpotVMConfig")) { config = new HotSpotVMConfig(compilerToVm); } @@ -135,10 +129,8 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H factory = findFactory(hostArchitecture); } - CompilerFactory compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory(); - try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) { - hostBackend = registerBackend(factory.createJVMCIBackend(this, compilerFactory, null)); + hostBackend = registerBackend(factory.createJVMCIBackend(this, null)); } vmEventListeners = Services.load(HotSpotVMEventListener.class); @@ -154,6 +146,12 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H context = new HotSpotJVMCIMetaAccessContext(); } metaAccessContext = context; + + if (Boolean.valueOf(System.getProperty("jvmci.printconfig"))) { + printConfig(config, compilerToVm); + } + + trivialPrefixes = HotSpotJVMCICompilerConfig.getCompilerFactory().getTrivialPrefixes(); } private JVMCIBackend registerBackend(JVMCIBackend backend) { @@ -179,7 +177,14 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H return metaAccessContext; } - public Compiler getCompiler() { + public JVMCICompiler getCompiler() { + if (compiler == null) { + synchronized (this) { + if (compiler == null) { + compiler = HotSpotJVMCICompilerConfig.getCompilerFactory().createCompiler(this); + } + } + } return compiler; } @@ -211,7 +216,7 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H return backends.get(arch); } - public Map, JVMCIBackend> getBackends() { + public Map, JVMCIBackend> getJVMCIBackends() { return Collections.unmodifiableMap(backends); } @@ -220,7 +225,7 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H */ @SuppressWarnings({"unused"}) private void compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) { - compiler.compileMethod(method, entryBCI, jvmciEnv, id); + getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id)); } /** @@ -247,4 +252,105 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compResult); } } + + private static void printConfig(HotSpotVMConfig config, CompilerToVM vm) { + Field[] fields = config.getClass().getDeclaredFields(); + Map sortedFields = new TreeMap<>(); + for (Field f : fields) { + if (!f.isSynthetic() && !Modifier.isStatic(f.getModifiers())) { + f.setAccessible(true); + sortedFields.put(f.getName(), f); + } + } + for (Field f : sortedFields.values()) { + try { + String line = String.format("%9s %-40s = %s%n", f.getType().getSimpleName(), f.getName(), pretty(f.get(config))); + byte[] lineBytes = line.getBytes(); + vm.writeDebugOutput(lineBytes, 0, lineBytes.length); + vm.flushDebugOutput(); + } catch (Exception e) { + } + } + } + + private static String pretty(Object value) { + if (value == null) { + return "null"; + } + + Class klass = value.getClass(); + if (value instanceof String) { + return "\"" + value + "\""; + } else if (value instanceof Method) { + return "method \"" + ((Method) value).getName() + "\""; + } else if (value instanceof Class) { + return "class \"" + ((Class) value).getSimpleName() + "\""; + } else if (value instanceof Integer) { + if ((Integer) value < 10) { + return value.toString(); + } + return value + " (0x" + Integer.toHexString((Integer) value) + ")"; + } else if (value instanceof Long) { + if ((Long) value < 10 && (Long) value > -10) { + return value + "l"; + } + return value + "l (0x" + Long.toHexString((Long) value) + "l)"; + } else if (klass.isArray()) { + StringBuilder str = new StringBuilder(); + int dimensions = 0; + while (klass.isArray()) { + dimensions++; + klass = klass.getComponentType(); + } + int length = Array.getLength(value); + str.append(klass.getSimpleName()).append('[').append(length).append(']'); + for (int i = 1; i < dimensions; i++) { + str.append("[]"); + } + str.append(" {"); + for (int i = 0; i < length; i++) { + str.append(pretty(Array.get(value, i))); + if (i < length - 1) { + str.append(", "); + } + } + str.append('}'); + return str.toString(); + } + return value.toString(); + } + + public OutputStream getLogStream() { + return new OutputStream() { + + @Override + public void write(byte[] b, int off, int len) throws IOException { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || off > b.length || len < 0 || (off + len) > b.length || (off + len) < 0) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return; + } + compilerToVm.writeDebugOutput(b, off, len); + } + + @Override + public void write(int b) throws IOException { + write(new byte[]{(byte) b}, 0, 1); + } + + @Override + public void flush() throws IOException { + compilerToVm.flushDebugOutput(); + } + }; + } + + /** + * Collects the current values of all JVMCI benchmark counters, summed up over all threads. + */ + public long[] collectCounters() { + return compilerToVm.collectCounters(); + } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java index 13665ac0f56..12cc5255ead 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java @@ -22,11 +22,15 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.common.*; -import jdk.vm.ci.compiler.Compiler; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.runtime.*; -import sun.misc.*; +import java.io.OutputStream; + +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.JVMCIMetaAccessContext; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.runtime.JVMCIRuntime; +import sun.misc.Unsafe; //JaCoCo Exclude @@ -39,7 +43,10 @@ public interface HotSpotJVMCIRuntimeProvider extends JVMCIRuntime { CompilerToVM getCompilerToVM(); - Compiler getCompiler(); + /** + * Gets an output stream that writes to the HotSpot's {@code tty} stream. + */ + OutputStream getLogStream(); /** * Converts a name to a Java type. This method attempts to resolve {@code name} to a @@ -70,7 +77,7 @@ public interface HotSpotJVMCIRuntimeProvider extends JVMCIRuntime { * * @return the offset in bytes */ - default int getArrayBaseOffset(JavaKind kind) { + static int getArrayBaseOffset(JavaKind kind) { switch (kind) { case Boolean: return Unsafe.ARRAY_BOOLEAN_BASE_OFFSET; @@ -100,7 +107,7 @@ public interface HotSpotJVMCIRuntimeProvider extends JVMCIRuntime { * * @return the scale in order to convert the index into a byte offset */ - default int getArrayIndexScale(JavaKind kind) { + static int getArrayIndexScale(JavaKind kind) { switch (kind) { case Boolean: return Unsafe.ARRAY_BOOLEAN_INDEX_SCALE; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJavaType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJavaType.java index 8c1a9808d7e..ef8253596d8 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJavaType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJavaType.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaType; /** * Common base class for all HotSpot {@link JavaType} implementations. @@ -39,5 +39,4 @@ public abstract class HotSpotJavaType implements JavaType { public final String getName() { return name; } - } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java index ed48d9b34f4..a352bb4d842 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java @@ -22,8 +22,10 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.hotspot.HotSpotVMConfig.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.hotspot.HotSpotVMConfig.CompressEncoding; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.MemoryAccessProvider; /** * HotSpot specific extension of {@link MemoryAccessProvider}. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java index 40efe0319c5..953f00f9884 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java @@ -23,8 +23,6 @@ package jdk.vm.ci.hotspot; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; - -import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.hotspot.HotSpotVMConfig.CompressEncoding; import jdk.vm.ci.meta.Constant; @@ -36,7 +34,7 @@ import jdk.vm.ci.meta.PrimitiveConstant; /** * HotSpot implementation of {@link MemoryAccessProvider}. */ -public class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider, HotSpotProxified { +class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider, HotSpotProxified { protected final HotSpotJVMCIRuntimeProvider runtime; @@ -54,7 +52,7 @@ public class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvi private boolean isValidObjectFieldDisplacement(Constant base, long displacement) { if (base instanceof HotSpotMetaspaceConstant) { - Object metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base); + MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base); if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) { if (displacement == runtime.getConfig().classMirrorOffset) { // Klass::_java_mirror is valid for all Klass* values @@ -68,8 +66,9 @@ public class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvi } private static long asRawPointer(Constant base) { - if (base instanceof HotSpotMetaspaceConstant) { - return ((HotSpotMetaspaceConstant) base).rawValue(); + if (base instanceof HotSpotMetaspaceConstantImpl) { + MetaspaceWrapperObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base); + return meta.getMetaspacePointer(); } else if (base instanceof PrimitiveConstant) { PrimitiveConstant prim = (PrimitiveConstant) base; if (prim.getJavaKind().isNumericInteger()) { @@ -119,7 +118,7 @@ public class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvi } } if (base instanceof HotSpotMetaspaceConstant) { - Object metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base); + MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base); if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) { if (displacement == runtime.getConfig().classMirrorOffset) { assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror(); @@ -211,8 +210,7 @@ public class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvi if (klass == null) { return JavaConstant.NULL_POINTER; } - TargetDescription target = runtime.getHostJVMCIBackend().getCodeCache().getTarget(); - return HotSpotMetaspaceConstantImpl.forMetaspaceObject(target.wordKind, klass.getMetaspaceKlass(), klass, false); + return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, false); } @Override @@ -221,15 +219,14 @@ public class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvi if (klass == null) { return HotSpotCompressedNullConstant.COMPRESSED_NULL; } - return HotSpotMetaspaceConstantImpl.forMetaspaceObject(JavaKind.Int, encoding.compress(klass.getMetaspaceKlass()), klass, true); + return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, true); } @Override public Constant readMethodPointerConstant(Constant base, long displacement) { - TargetDescription target = runtime.getHostJVMCIBackend().getCodeCache().getTarget(); assert (base instanceof HotSpotObjectConstantImpl); Object baseObject = ((HotSpotObjectConstantImpl) base).object(); HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod(baseObject, displacement); - return HotSpotMetaspaceConstantImpl.forMetaspaceObject(target.wordKind, method.getMetaspaceMethod(), method, false); + return HotSpotMetaspaceConstantImpl.forMetaspaceObject(method, false); } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java index e3fb69d8b80..5bd116cd57b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java @@ -22,14 +22,31 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; +import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; -import java.lang.reflect.*; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; -import jdk.vm.ci.code.*; -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.CodeUtil; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.DeoptimizationAction; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; // JaCoCo Exclude @@ -292,9 +309,9 @@ public class HotSpotMetaAccessProvider implements MetaAccessProvider, HotSpotPro int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object()); ResolvedJavaType elementType = lookupJavaType.getComponentType(); JavaKind elementKind = elementType.getJavaKind(); - final int headerSize = runtime.getArrayBaseOffset(elementKind); + final int headerSize = getArrayBaseOffset(elementKind); TargetDescription target = runtime.getHostJVMCIBackend().getTarget(); - int sizeOfElement = target.getSizeInBytes(elementKind); + int sizeOfElement = getArrayIndexScale(elementKind); int alignment = target.wordSize; int log2ElementSize = CodeUtil.log2(sizeOfElement); return computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java index fd40b38a7e8..95a9670f311 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java @@ -22,6 +22,8 @@ */ package jdk.vm.ci.hotspot; +import jdk.vm.ci.inittimer.SuppressFBWarnings; + public class HotSpotMetaData { @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] pcDescBytes; @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] scopesDescBytes; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstant.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstant.java index d37328eb269..a19aa486e2c 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstant.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstant.java @@ -22,18 +22,11 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.hotspot.HotSpotVMConfig.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.VMConstant; public interface HotSpotMetaspaceConstant extends HotSpotConstant, VMConstant { - Constant compress(CompressEncoding encoding); - - Constant uncompress(CompressEncoding encoding); - HotSpotResolvedObjectType asResolvedJavaType(); HotSpotResolvedJavaMethod asResolvedJavaMethod(); - - long rawValue(); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java index 35e4519c4c1..43051ab5e2a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java @@ -22,59 +22,75 @@ */ package jdk.vm.ci.hotspot; -import java.util.*; +import java.util.Objects; -import jdk.vm.ci.hotspot.HotSpotVMConfig.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.VMConstant; -public final class HotSpotMetaspaceConstantImpl extends PrimitiveConstant implements HotSpotMetaspaceConstant, VMConstant, HotSpotProxified { +final class HotSpotMetaspaceConstantImpl implements HotSpotMetaspaceConstant, VMConstant, HotSpotProxified { - static HotSpotMetaspaceConstantImpl forMetaspaceObject(JavaKind kind, long primitive, Object metaspaceObject, boolean compressed) { - return new HotSpotMetaspaceConstantImpl(kind, primitive, metaspaceObject, compressed); + static HotSpotMetaspaceConstantImpl forMetaspaceObject(MetaspaceWrapperObject metaspaceObject, boolean compressed) { + return new HotSpotMetaspaceConstantImpl(metaspaceObject, compressed); } - static Object getMetaspaceObject(Constant constant) { + static MetaspaceWrapperObject getMetaspaceObject(Constant constant) { return ((HotSpotMetaspaceConstantImpl) constant).metaspaceObject; } - private final Object metaspaceObject; + private final MetaspaceWrapperObject metaspaceObject; private final boolean compressed; - private HotSpotMetaspaceConstantImpl(JavaKind kind, long primitive, Object metaspaceObject, boolean compressed) { - super(kind, primitive); + private HotSpotMetaspaceConstantImpl(MetaspaceWrapperObject metaspaceObject, boolean compressed) { this.metaspaceObject = metaspaceObject; this.compressed = compressed; } @Override public int hashCode() { - return super.hashCode() ^ System.identityHashCode(metaspaceObject); + return System.identityHashCode(metaspaceObject) ^ (compressed ? 1 : 2); } @Override public boolean equals(Object o) { - return o == this || (o instanceof HotSpotMetaspaceConstantImpl && super.equals(o) && Objects.equals(metaspaceObject, ((HotSpotMetaspaceConstantImpl) o).metaspaceObject)); + if (o == this) { + return true; + } + if (!(o instanceof HotSpotMetaspaceConstantImpl)) { + return false; + } + + HotSpotMetaspaceConstantImpl other = (HotSpotMetaspaceConstantImpl) o; + return Objects.equals(this.metaspaceObject, other.metaspaceObject) && this.compressed == other.compressed; + } + + @Override + public String toValueString() { + return String.format("meta{%s%s}", metaspaceObject, compressed ? ";compressed" : ""); } @Override public String toString() { - return super.toString() + "{" + metaspaceObject + (compressed ? ";compressed}" : "}"); + return toValueString(); + } + + public boolean isDefaultForKind() { + return false; } public boolean isCompressed() { return compressed; } - public JavaConstant compress(CompressEncoding encoding) { + public Constant compress() { assert !isCompressed(); - HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(JavaKind.Int, encoding.compress(asLong()), metaspaceObject, true); + HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(metaspaceObject, true); assert res.isCompressed(); return res; } - public JavaConstant uncompress(CompressEncoding encoding) { + public Constant uncompress() { assert isCompressed(); - HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(JavaKind.Long, encoding.uncompress(asInt()), metaspaceObject, false); + HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(metaspaceObject, false); assert !res.isCompressed(); return res; } @@ -92,8 +108,4 @@ public final class HotSpotMetaspaceConstantImpl extends PrimitiveConstant implem } return null; } - - public long rawValue() { - return asLong(); - } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java index c6e8e72869e..3fa045a618e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -22,12 +22,17 @@ */ package jdk.vm.ci.hotspot; -import static java.util.FormattableFlags.*; -import java.util.*; +import static java.util.FormattableFlags.ALTERNATE; +import static java.util.FormattableFlags.LEFT_JUSTIFY; +import static java.util.FormattableFlags.UPPERCASE; -import jdk.vm.ci.meta.*; +import java.util.Formattable; +import java.util.Formatter; -public abstract class HotSpotMethod implements JavaMethod, Formattable /* , JavaMethodContex */{ +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +abstract class HotSpotMethod implements JavaMethod, Formattable /* , JavaMethodContex */{ public static String applyFormattingFlagsAndWidth(String s, int flags, int width) { if (flags == 0 && width < 0) { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java index 8fed389a799..1741a080720 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java @@ -22,24 +22,31 @@ */ package jdk.vm.ci.hotspot; -import static java.lang.String.*; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*; +import static java.lang.String.format; +import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; -import java.util.*; +import java.util.Arrays; -import jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.meta.JavaMethodProfile.*; -import jdk.vm.ci.meta.JavaTypeProfile.*; -import sun.misc.*; +import jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.Tag; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaMethodProfile; +import jdk.vm.ci.meta.JavaMethodProfile.ProfiledMethod; +import jdk.vm.ci.meta.JavaTypeProfile; +import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.TriState; +import sun.misc.Unsafe; /** * Access to a HotSpot MethodData structure (defined in methodData.hpp). */ public final class HotSpotMethodData { - private static final HotSpotVMConfig config = runtime().getConfig(); + private static final HotSpotVMConfig config = config(); private static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(TriState.FALSE); private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(TriState.UNKNOWN); @@ -50,16 +57,16 @@ public final class HotSpotMethodData { new BitData(), new CounterData(), new JumpData(), - new TypeCheckData(), + new ReceiverTypeData(), new VirtualCallData(), new RetData(), new BranchData(), new MultiBranchData(), new ArgInfoData(), - null, // call_type_data_tag - null, // virtual_call_type_data_tag - null, // parameters_type_data_tag - null, // speculative_trap_data_tag + new UnknownProfileData(Tag.CallTypeData), + new VirtualCallTypeData(), + new UnknownProfileData(Tag.ParametersTypeData), + new UnknownProfileData(Tag.SpeculativeTrapData), }; // @formatter:on @@ -127,7 +134,8 @@ public final class HotSpotMethodData { } HotSpotMethodDataAccessor result = getData(position); - assert result != null : "NO_DATA tag is not allowed"; + final Tag tag = AbstractMethodData.readTag(this, position); + assert result != null : "NO_DATA tag is not allowed " + tag; return result; } @@ -193,12 +201,12 @@ public final class HotSpotMethodData { private HotSpotResolvedJavaMethod readMethod(int position, int offsetInBytes) { long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); - return runtime().compilerToVm.getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes); + return compilerToVM().getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes); } private HotSpotResolvedObjectTypeImpl readKlass(int position, int offsetInBytes) { long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); - return runtime().compilerToVm.getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false); + return compilerToVM().getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false); } private static int truncateLongToInt(long value) { @@ -266,10 +274,10 @@ public final class HotSpotMethodData { /** * Corresponds to {@code exception_seen_flag}. */ - private static final int EXCEPTIONS_MASK = 0x2; + private static final int EXCEPTIONS_MASK = 1 << config.bitDataExceptionSeenFlag; private final Tag tag; - private final int staticSize; + protected final int staticSize; protected AbstractMethodData(Tag tag, int staticSize) { this.tag = tag; @@ -291,8 +299,12 @@ public final class HotSpotMethodData { } @Override - public int getSize(HotSpotMethodData data, int position) { - return staticSize + getDynamicSize(data, position); + public final int getSize(HotSpotMethodData data, int position) { + int size = staticSize + getDynamicSize(data, position); + // Sanity check against VM + int vmSize = HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position); + assert size == vmSize : size + " != " + vmSize; + return size; } @Override @@ -375,7 +387,7 @@ public final class HotSpotMethodData { private static class BitData extends AbstractMethodData { private static final int BIT_DATA_SIZE = cellIndexToOffset(0); - private static final int BIT_DATA_NULL_SEEN_FLAG = 0x01; + private static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag; private BitData() { super(Tag.BitData, BIT_DATA_SIZE); @@ -399,7 +411,7 @@ public final class HotSpotMethodData { private static class CounterData extends BitData { private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1); - private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(0); + private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset); public CounterData() { super(Tag.CounterData, COUNTER_DATA_SIZE); @@ -427,8 +439,8 @@ public final class HotSpotMethodData { private static class JumpData extends AbstractMethodData { private static final int JUMP_DATA_SIZE = cellIndexToOffset(2); - protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(0); - protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(1); + protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset); + protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset); public JumpData() { super(Tag.JumpData, JUMP_DATA_SIZE); @@ -474,11 +486,11 @@ public final class HotSpotMethodData { private abstract static class AbstractTypeData extends CounterData { - protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(2); + protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount); - protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(1); - protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(2); - protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(3); + protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset); + protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(config.receiverTypeDataReceiver0Offset); + protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataCount0Offset); protected AbstractTypeData(Tag tag, int staticSize) { super(tag, staticSize); @@ -571,14 +583,18 @@ public final class HotSpotMethodData { } } - private static class TypeCheckData extends AbstractTypeData { + private static class ReceiverTypeData extends AbstractTypeData { private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth; - public TypeCheckData() { + public ReceiverTypeData() { super(Tag.ReceiverTypeData, TYPE_CHECK_DATA_SIZE); } + protected ReceiverTypeData(Tag tag, int staticSize) { + super(tag, staticSize); + } + @Override public int getExecutionCount(HotSpotMethodData data, int position) { return -1; @@ -590,7 +606,7 @@ public final class HotSpotMethodData { } } - private static class VirtualCallData extends AbstractTypeData { + private static class VirtualCallData extends ReceiverTypeData { private static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth); private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth; @@ -600,6 +616,10 @@ public final class HotSpotMethodData { super(Tag.VirtualCallData, VIRTUAL_CALL_DATA_SIZE); } + protected VirtualCallData(Tag tag, int staticSize) { + super(tag, staticSize); + } + @Override public int getExecutionCount(HotSpotMethodData data, int position) { final int typeProfileWidth = config.typeProfileWidth; @@ -692,6 +712,19 @@ public final class HotSpotMethodData { } } + private static class VirtualCallTypeData extends VirtualCallData { + + public VirtualCallTypeData() { + super(Tag.VirtualCallTypeData, 0); + } + + @Override + protected int getDynamicSize(HotSpotMethodData data, int position) { + assert staticSize == 0; + return HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position); + } + } + private static class RetData extends CounterData { private static final int RET_DATA_ROW_SIZE = cellsToBytes(3); @@ -705,7 +738,7 @@ public final class HotSpotMethodData { private static class BranchData extends JumpData { private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3); - private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(2); + private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset); public BranchData() { super(Tag.BranchData, BRANCH_DATA_SIZE); @@ -737,8 +770,8 @@ public final class HotSpotMethodData { private static class ArrayData extends AbstractMethodData { - private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(0); - protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(1); + private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset); + protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset); public ArrayData(Tag tag, int staticSize) { super(tag, staticSize); @@ -762,7 +795,7 @@ public final class HotSpotMethodData { private static class MultiBranchData extends ArrayData { private static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1); - private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = 2; + private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = config.multiBranchDataPerCaseCellCount; private static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS); private static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0); private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1); @@ -854,6 +887,24 @@ public final class HotSpotMethodData { } } + private static class UnknownProfileData extends AbstractMethodData { + public UnknownProfileData(Tag tag) { + super(tag, 0); + } + + @Override + protected int getDynamicSize(HotSpotMethodData data, int position) { + assert staticSize == 0; + return HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position); + } + + @Override + public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) { + // TODO Auto-generated method stub + return null; + } + } + public void setCompiledIRSize(int size) { UNSAFE.putInt(metaspaceMethodData + config.methodDataIRSizeOffset, size); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java index 7f5ceacd986..7ac97ebb59f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java @@ -22,9 +22,11 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*; - -import jdk.vm.ci.meta.*; +import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; +import jdk.vm.ci.meta.JavaMethodProfile; +import jdk.vm.ci.meta.JavaTypeProfile; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.TriState; /** * Interface for accessor objects that encapsulate the logic for accessing the different kinds of @@ -62,10 +64,6 @@ public interface HotSpotMethodDataAccessor { return value; } - private static HotSpotVMConfig config() { - return runtime().getConfig(); - } - public static Tag getEnum(int value) { Tag result = values()[value]; assert value == result.value; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java index 40c1d67a869..87cf467f6d7 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java @@ -22,11 +22,16 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*; -import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*; - -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; +import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProvider, HotSpotProxified { @@ -155,6 +160,6 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv Object object = ((HotSpotObjectConstantImpl) memberName).object(); /* Read the ResolvedJavaMethod from the injected field MemberName.vmtarget */ - return runtime().compilerToVm.getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset()); + return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset()); } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java index 134e69c28bb..b859c124a4d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java @@ -22,12 +22,14 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.Signature; /** * Implementation of {@link JavaMethod} for unresolved HotSpot methods. */ -public final class HotSpotMethodUnresolved extends HotSpotMethod { +final class HotSpotMethodUnresolved extends HotSpotMethod { private final Signature signature; protected JavaType holder; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java index 83219dec4b7..f8aa3cb9310 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java @@ -22,10 +22,12 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*; - -import jdk.vm.ci.code.*; -import jdk.vm.ci.meta.*; +import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.InvalidInstalledCodeException; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Implementation of {@link InstalledCode} for code installed as an nmethod. The nmethod stores a @@ -45,34 +47,24 @@ public class HotSpotNmethod extends HotSpotInstalledCode { private final HotSpotResolvedJavaMethod method; private final boolean isDefault; - private final boolean isExternal; public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault) { - this(method, name, isDefault, false); - } - - public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault, boolean isExternal) { super(name); this.method = method; this.isDefault = isDefault; - this.isExternal = isExternal; } public boolean isDefault() { return isDefault; } - public boolean isExternal() { - return isExternal; - } - public ResolvedJavaMethod getMethod() { return method; } @Override public void invalidate() { - runtime().getCompilerToVM().invalidateInstalledCode(this); + compilerToVM().invalidateInstalledCode(this); } @Override @@ -105,8 +97,7 @@ public class HotSpotNmethod extends HotSpotInstalledCode { @Override public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { assert checkArgs(args); - assert !isExternal(); - return runtime().getCompilerToVM().executeInstalledCode(args, this); + return compilerToVM().executeInstalledCode(args, this); } @Override diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstant.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstant.java index 6edf5ac3339..408f7268260 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstant.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstant.java @@ -22,10 +22,13 @@ */ package jdk.vm.ci.hotspot; -import java.lang.invoke.*; -import java.util.*; +import java.lang.invoke.CallSite; +import java.util.Objects; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.VMConstant; /** * Represents a constant non-{@code null} object reference, within the compiler and across the diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java index e3c7cb32da9..0dd51105445 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java @@ -22,20 +22,26 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*; +import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass; -import java.lang.invoke.*; +import java.lang.invoke.CallSite; +import java.lang.invoke.ConstantCallSite; +import java.lang.invoke.MethodHandle; -import jdk.vm.ci.inittimer.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.inittimer.SuppressFBWarnings; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Represents a constant non-{@code null} object reference, within the compiler and across the * compiler/runtime interface. */ -public final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotProxified { +final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotProxified { - public static JavaConstant forObject(Object object) { + static JavaConstant forObject(Object object) { return forObject(object, false); } @@ -106,21 +112,6 @@ public final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, H return object; } - /** - * Determines if the object represented by this constant is {@link Object#equals(Object) equal} - * to a given object. - */ - public boolean isEqualTo(Object obj) { - return object.equals(obj); - } - - /** - * Gets the class of the object represented by this constant. - */ - public Class getObjectClass() { - return object.getClass(); - } - public boolean isCompressed() { return compressed; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotOopMap.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotOopMap.java index bedd564694c..06f2983c645 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotOopMap.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotOopMap.java @@ -22,6 +22,8 @@ */ package jdk.vm.ci.hotspot; +import jdk.vm.ci.inittimer.SuppressFBWarnings; + public class HotSpotOopMap { @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int offset; @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int count; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java index 7da7d4e042d..020343e164c 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java @@ -22,7 +22,11 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaMethodProfile; +import jdk.vm.ci.meta.JavaTypeProfile; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.TriState; public final class HotSpotProfilingInfo implements ProfilingInfo, HotSpotProxified { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java index a35585a0d6c..5bb7c66cf45 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java @@ -22,9 +22,10 @@ */ package jdk.vm.ci.hotspot; -import java.util.*; +import java.util.Arrays; -import jdk.vm.ci.code.*; +import jdk.vm.ci.code.Location; +import jdk.vm.ci.code.ReferenceMap; public final class HotSpotReferenceMap extends ReferenceMap { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaField.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaField.java index aba4598b016..00b0c0de8c9 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaField.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaField.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ResolvedJavaField; /** * Represents a field in a HotSpot type. @@ -45,4 +45,12 @@ public interface HotSpotResolvedJavaField extends ResolvedJavaField { * @return true if field has {@link Stable} annotation, false otherwise */ boolean isStable(); + + /** + * If this field is stable, checks if default values (0, null, etc.) should be considered stable + * as well. + * + * @return true if default values should be considered stable, false otherwise + */ + boolean isDefaultStable(); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 4535cefce85..cd89be3e563 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -22,20 +22,27 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*; -import static jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl.Options.*; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; -import java.lang.annotation.*; -import java.lang.reflect.*; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.options.*; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.LocationIdentity; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ModifiersProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.options.Option; +import jdk.vm.ci.options.OptionType; +import jdk.vm.ci.options.OptionValue; /** * Represents a field in a HotSpot type. */ -public class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotProxified { +class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotProxified { static class Options { //@formatter:off @@ -91,7 +98,7 @@ public class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, H } } - public HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, String name, JavaType type, long offset, int modifiers) { + HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, String name, JavaType type, long offset, int modifiers) { this.holder = holder; this.name = name; this.type = type; @@ -130,7 +137,7 @@ public class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, H @Override public boolean isInternal() { - return (modifiers & runtime().getConfig().jvmAccFieldInternal) != 0; + return (modifiers & config().jvmAccFieldInternal) != 0; } /** @@ -183,7 +190,7 @@ public class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, H @Override public boolean isSynthetic() { - return (runtime().getConfig().syntheticFlag & modifiers) != 0; + return (config().syntheticFlag & modifiers) != 0; } /** @@ -192,11 +199,11 @@ public class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, H * @return true if field has {@link Stable} annotation, false otherwise */ public boolean isStable() { - if ((runtime().getConfig().jvmAccFieldStable & modifiers) != 0) { + if ((config().jvmAccFieldStable & modifiers) != 0) { return true; } assert getAnnotation(Stable.class) == null; - if (ImplicitStableValues.getValue() && isImplicitStableField()) { + if (Options.ImplicitStableValues.getValue() && isImplicitStableField()) { return true; } return false; @@ -243,19 +250,25 @@ public class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, H } private boolean isImplicitStableField() { - if (isSynthetic()) { - if (isSyntheticImplicitStableField()) { - return true; - } - } else if (isWellKnownImplicitStableField()) { + if (isSyntheticEnumSwitchMap()) { + return true; + } + if (isWellKnownImplicitStableField()) { return true; } return false; } - private boolean isSyntheticImplicitStableField() { - assert this.isSynthetic(); - if (isStatic() && isArray()) { + public boolean isDefaultStable() { + assert this.isStable(); + if (isSyntheticEnumSwitchMap()) { + return true; + } + return false; + } + + private boolean isSyntheticEnumSwitchMap() { + if (isSynthetic() && isStatic() && isArray()) { if (isFinal() && name.equals("$VALUES") || name.equals("ENUM$VALUES")) { // generated int[] field for EnumClass::values() return true; @@ -281,6 +294,7 @@ public class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, H } private static final ResolvedJavaField STRING_VALUE_FIELD; + static { try { MetaAccessProvider metaAccess = runtime().getHostJVMCIBackend().getMetaAccess(); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java index 2f91cbe59dc..d1ecdac098d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -22,15 +22,27 @@ */ package jdk.vm.ci.hotspot; -import java.lang.reflect.*; +import java.lang.reflect.Modifier; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.options.Option; +import jdk.vm.ci.options.OptionType; +import jdk.vm.ci.options.OptionValue; /** * Implementation of {@link JavaMethod} for resolved HotSpot methods. */ public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod { + public static class Options { + // @formatter:off + @Option(help = "", type = OptionType.Debug) + public static final OptionValue UseProfilingInformation = new OptionValue<>(true); + // @formatter:on + } + /** * Returns true if this method has a {@code CallerSensitive} annotation. * diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 7e931f370ee..4b7184e0529 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -22,29 +22,47 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*; -import static jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.Options.*; +import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod.Options.UseProfilingInformation; +import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.util.*; +import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.options.*; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.DefaultProfilingInfo; +import jdk.vm.ci.meta.ExceptionHandler; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.LineNumberTable; +import jdk.vm.ci.meta.LineNumberTableImpl; +import jdk.vm.ci.meta.Local; +import jdk.vm.ci.meta.LocalImpl; +import jdk.vm.ci.meta.LocalVariableTable; +import jdk.vm.ci.meta.LocalVariableTableImpl; +import jdk.vm.ci.meta.ModifiersProvider; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.meta.SpeculationLog; +import jdk.vm.ci.meta.TriState; /** * Implementation of {@link JavaMethod} for resolved HotSpot methods. */ -public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, HotSpotProxified, MetaspaceWrapperObject { - - public static class Options { - // @formatter:off - @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseProfilingInformation = new OptionValue<>(true); - // @formatter:on - } +final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, HotSpotProxified, MetaspaceWrapperObject { /** * Reference to metaspace Method object. @@ -56,7 +74,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement private final HotSpotSignature signature; private HotSpotMethodData methodData; private byte[] code; - private Member toJavaCache; + private Executable toJavaCache; /** * Gets the holder of a HotSpot metaspace method native object. @@ -66,10 +84,10 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * {@code metaspaceMethod} */ private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceMethod) { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); final long metaspaceConstMethod = UNSAFE.getAddress(metaspaceMethod + config.methodConstMethodOffset); final long metaspaceConstantPool = UNSAFE.getAddress(metaspaceConstMethod + config.constMethodConstantsOffset); - return runtime().getCompilerToVM().getResolvedJavaType(null, metaspaceConstantPool + config.constantPoolHolderOffset, false); + return compilerToVM().getResolvedJavaType(null, metaspaceConstantPool + config.constantPoolHolderOffset, false); } /** @@ -94,7 +112,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement this.metaspaceMethod = metaspaceMethod; this.holder = holder; - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); final long constMethod = getConstMethod(); /* @@ -106,7 +124,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement if (metaspaceConstantPool == holder.getConstantPool().getMetaspaceConstantPool()) { this.constantPool = holder.getConstantPool(); } else { - this.constantPool = runtime().getCompilerToVM().getConstantPool(null, constMethod + config.constMethodConstantsOffset); + this.constantPool = compilerToVM().getConstantPool(null, constMethod + config.constMethodConstantsOffset); } final int nameIndex = UNSAFE.getChar(constMethod + config.constMethodNameIndexOffset); @@ -126,7 +144,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement */ private long getConstMethod() { assert metaspaceMethod != 0; - return UNSAFE.getAddress(metaspaceMethod + runtime().getConfig().methodConstMethodOffset); + return UNSAFE.getAddress(metaspaceMethod + config().methodConstMethodOffset); } @Override @@ -152,7 +170,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * @return flags of this method */ private int getFlags() { - return UNSAFE.getByte(metaspaceMethod + runtime().getConfig().methodFlagsOffset); + return UNSAFE.getByte(metaspaceMethod + config().methodFlagsOffset); } /** @@ -161,7 +179,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * @return flags of this method's ConstMethod */ private int getConstMethodFlags() { - return UNSAFE.getChar(getConstMethod() + runtime().getConfig().constMethodFlagsOffset); + return UNSAFE.getChar(getConstMethod() + config().constMethodFlagsOffset); } @Override @@ -172,20 +190,16 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement /** * Gets the address of the C++ Method object for this method. */ - public JavaConstant getMetaspaceMethodConstant() { - return HotSpotMetaspaceConstantImpl.forMetaspaceObject(getHostWordKind(), metaspaceMethod, this, false); - } - - public long getMetaspaceMethod() { - return metaspaceMethod; + public Constant getMetaspaceMethodConstant() { + return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false); } public long getMetaspacePointer() { - return getMetaspaceMethod(); + return metaspaceMethod; } @Override - public JavaConstant getEncoding() { + public Constant getEncoding() { return getMetaspaceMethodConstant(); } @@ -194,7 +208,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * modifiers as well as the HotSpot internal modifiers. */ public int getAllModifiers() { - return UNSAFE.getInt(metaspaceMethod + runtime().getConfig().methodAccessFlagsOffset); + return UNSAFE.getInt(metaspaceMethod + config().methodAccessFlagsOffset); } @Override @@ -213,7 +227,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement return null; } if (code == null && holder.isLinked()) { - code = runtime().getCompilerToVM().getBytecode(this); + code = compilerToVM().getBytecode(this); assert code.length == getCodeSize() : "expected: " + getCodeSize() + ", actual: " + code.length; } return code; @@ -221,20 +235,20 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement @Override public int getCodeSize() { - return UNSAFE.getChar(getConstMethod() + runtime().getConfig().constMethodCodeSizeOffset); + return UNSAFE.getChar(getConstMethod() + config().constMethodCodeSizeOffset); } @Override public ExceptionHandler[] getExceptionHandlers() { - final boolean hasExceptionTable = (getConstMethodFlags() & runtime().getConfig().constMethodHasExceptionTable) != 0; + final boolean hasExceptionTable = (getConstMethodFlags() & config().constMethodHasExceptionTable) != 0; if (!hasExceptionTable) { return new ExceptionHandler[0]; } - HotSpotVMConfig config = runtime().getConfig(); - final int exceptionTableLength = runtime().getCompilerToVM().getExceptionTableLength(this); + HotSpotVMConfig config = config(); + final int exceptionTableLength = compilerToVM().getExceptionTableLength(this); ExceptionHandler[] handlers = new ExceptionHandler[exceptionTableLength]; - long exceptionTableElement = runtime().getCompilerToVM().getExceptionTableStart(this); + long exceptionTableElement = compilerToVM().getExceptionTableStart(this); for (int i = 0; i < exceptionTableLength; i++) { final int startPc = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementStartPcOffset); @@ -273,7 +287,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * @return true if CallerSensitive annotation present, false otherwise */ public boolean isCallerSensitive() { - return (getFlags() & runtime().getConfig().methodFlagsCallerSensitive) != 0; + return (getFlags() & config().methodFlagsCallerSensitive) != 0; } /** @@ -282,7 +296,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * @return true if ForceInline annotation present, false otherwise */ public boolean isForceInline() { - return (getFlags() & runtime().getConfig().methodFlagsForceInline) != 0; + return (getFlags() & config().methodFlagsForceInline) != 0; } /** @@ -291,14 +305,14 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * @return true if DontInline annotation present, false otherwise */ public boolean isDontInline() { - return (getFlags() & runtime().getConfig().methodFlagsDontInline) != 0; + return (getFlags() & config().methodFlagsDontInline) != 0; } /** * Manually adds a DontInline annotation to this method. */ public void setNotInlineable() { - runtime().getCompilerToVM().doNotInlineOrCompile(this); + compilerToVM().doNotInlineOrCompile(this); } /** @@ -308,7 +322,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * @return true if special method ignored by security stack walks, false otherwise */ public boolean ignoredBySecurityStackWalk() { - return runtime().getCompilerToVM().methodIsIgnoredBySecurityStackWalk(this); + return compilerToVM().methodIsIgnoredBySecurityStackWalk(this); } @Override @@ -326,7 +340,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement if (isAbstract() || isNative()) { return 0; } - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); return UNSAFE.getChar(getConstMethod() + config.methodMaxLocalsOffset); } @@ -335,7 +349,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement if (isAbstract() || isNative()) { return 0; } - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); return config.extraStackEntries + UNSAFE.getChar(getConstMethod() + config.constMethodMaxStackOffset); } @@ -343,10 +357,10 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement public StackTraceElement asStackTraceElement(int bci) { if (bci < 0 || bci >= getCodeSize()) { // HotSpot code can only construct stack trace elements for valid bcis - StackTraceElement ste = runtime().getCompilerToVM().getStackTraceElement(this, 0); + StackTraceElement ste = compilerToVM().getStackTraceElement(this, 0); return new StackTraceElement(ste.getClassName(), ste.getMethodName(), ste.getFileName(), -1); } - return runtime().getCompilerToVM().getStackTraceElement(this, bci); + return compilerToVM().getStackTraceElement(this, bci); } public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) { @@ -361,7 +375,11 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement // seeing A.foo(). return null; } - return runtime().getCompilerToVM().findUniqueConcreteMethod(((HotSpotResolvedObjectTypeImpl) receiver), this); + if (this.isDefault()) { + // CHA for default methods doesn't work and may crash the VM + return null; + } + return compilerToVM().findUniqueConcreteMethod(((HotSpotResolvedObjectTypeImpl) receiver), this); } @Override @@ -375,7 +393,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * @return the value of {@code Method::_code} */ private long getCompiledCode() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); return UNSAFE.getAddress(metaspaceMethod + config.methodCodeOffset); } @@ -395,7 +413,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement public boolean hasCompiledCodeAtLevel(int level) { long compiledCode = getCompiledCode(); if (compiledCode != 0) { - return UNSAFE.getInt(compiledCode + runtime().getConfig().nmethodCompLevelOffset) == level; + return UNSAFE.getInt(compiledCode + config().nmethodCompLevelOffset) == level; } return false; } @@ -407,7 +425,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement ProfilingInfo info; if (UseProfilingInformation.getValue() && methodData == null) { - long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + runtime().getConfig().methodDataOffset); + long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + config().methodDataOffset); if (metaspaceMethodData != 0) { methodData = new HotSpotMethodData(metaspaceMethodData, this); if (TraceMethodDataFilter != null && this.format("%H.%n").contains(TraceMethodDataFilter)) { @@ -429,7 +447,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement @Override public void reprofile() { - runtime().getCompilerToVM().reprofile(this); + compilerToVM().reprofile(this); } @Override @@ -439,31 +457,19 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement @Override public Annotation[][] getParameterAnnotations() { - if (isConstructor()) { - Constructor javaConstructor = toJavaConstructor(); - return javaConstructor == null ? null : javaConstructor.getParameterAnnotations(); - } - Method javaMethod = toJava(); + Executable javaMethod = toJava(); return javaMethod == null ? null : javaMethod.getParameterAnnotations(); } @Override public Annotation[] getAnnotations() { - if (isConstructor()) { - Constructor javaConstructor = toJavaConstructor(); - return javaConstructor == null ? new Annotation[0] : javaConstructor.getAnnotations(); - } - Method javaMethod = toJava(); + Executable javaMethod = toJava(); return javaMethod == null ? new Annotation[0] : javaMethod.getAnnotations(); } @Override public T getAnnotation(Class annotationClass) { - if (isConstructor()) { - Constructor javaConstructor = toJavaConstructor(); - return javaConstructor == null ? null : javaConstructor.getAnnotation(annotationClass); - } - Method javaMethod = toJava(); + Executable javaMethod = toJava(); return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass); } @@ -478,11 +484,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement @Override public Type[] getGenericParameterTypes() { - if (isConstructor()) { - Constructor javaConstructor = toJavaConstructor(); - return javaConstructor == null ? null : javaConstructor.getGenericParameterTypes(); - } - Method javaMethod = toJava(); + Executable javaMethod = toJava(); return javaMethod == null ? null : javaMethod.getGenericParameterTypes(); } @@ -498,25 +500,13 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement return result; } - private Method toJava() { + private Executable toJava() { if (toJavaCache != null) { - return (Method) toJavaCache; + return toJavaCache; } try { - Method result = holder.mirror().getDeclaredMethod(name, signatureToTypes()); - toJavaCache = result; - return result; - } catch (NoSuchMethodException | NoClassDefFoundError e) { - return null; - } - } - - private Constructor toJavaConstructor() { - if (toJavaCache != null) { - return (Constructor) toJavaCache; - } - try { - Constructor result = holder.mirror().getDeclaredConstructor(signatureToTypes()); + Class[] parameterTypes = signatureToTypes(); + Executable result = isConstructor() ? holder.mirror().getDeclaredConstructor(parameterTypes) : holder.mirror().getDeclaredMethod(name, parameterTypes); toJavaCache = result; return result; } catch (NoSuchMethodException | NoClassDefFoundError e) { @@ -529,7 +519,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement if (isDontInline()) { return false; } - return runtime().getCompilerToVM().canInlineMethod(this); + return compilerToVM().canInlineMethod(this); } @Override @@ -537,17 +527,17 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement if (isForceInline()) { return true; } - return runtime().getCompilerToVM().shouldInlineMethod(this); + return compilerToVM().shouldInlineMethod(this); } @Override public LineNumberTable getLineNumberTable() { - final boolean hasLineNumberTable = (getConstMethodFlags() & runtime().getConfig().constMethodHasLineNumberTable) != 0; + final boolean hasLineNumberTable = (getConstMethodFlags() & config().constMethodHasLineNumberTable) != 0; if (!hasLineNumberTable) { return null; } - long[] values = runtime().getCompilerToVM().getLineNumberTable(this); + long[] values = compilerToVM().getLineNumberTable(this); if (values == null || values.length == 0) { // Empty table so treat is as non-existent return null; @@ -566,14 +556,14 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement @Override public LocalVariableTable getLocalVariableTable() { - final boolean hasLocalVariableTable = (getConstMethodFlags() & runtime().getConfig().constMethodHasLocalVariableTable) != 0; + final boolean hasLocalVariableTable = (getConstMethodFlags() & config().constMethodHasLocalVariableTable) != 0; if (!hasLocalVariableTable) { return null; } - HotSpotVMConfig config = runtime().getConfig(); - long localVariableTableElement = runtime().getCompilerToVM().getLocalVariableTableStart(this); - final int localVariableTableLength = runtime().getCompilerToVM().getLocalVariableTableLength(this); + HotSpotVMConfig config = config(); + long localVariableTableElement = compilerToVM().getLocalVariableTableStart(this); + final int localVariableTableLength = compilerToVM().getLocalVariableTableLength(this); Local[] locals = new Local[localVariableTableLength]; for (int i = 0; i < localVariableTableLength; i++) { @@ -606,7 +596,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement if (!isInVirtualMethodTable(resolved)) { throw new JVMCIError("%s does not have a vtable entry in type %s", this, resolved); } - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); final int vtableIndex = getVtableIndex((HotSpotResolvedObjectTypeImpl) resolved); return config.instanceKlassVtableStartOffset() + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset; } @@ -623,11 +613,11 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement private int getVtableIndex(HotSpotResolvedObjectTypeImpl resolved) { if (!holder.isLinked()) { - return runtime().getConfig().invalidVtableIndex; + return config().invalidVtableIndex; } if (holder.isInterface()) { if (resolved.isInterface()) { - return runtime().getConfig().invalidVtableIndex; + return config().invalidVtableIndex; } return getVtableIndexForInterfaceMethod(resolved); } @@ -640,8 +630,8 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * @return virtual table index */ private int getVtableIndex() { - assert!holder.isInterface(); - HotSpotVMConfig config = runtime().getConfig(); + assert !holder.isInterface(); + HotSpotVMConfig config = config(); int result = UNSAFE.getInt(metaspaceMethod + config.methodVtableIndexOffset); assert result >= config.nonvirtualVtableIndex : "must be linked"; return result; @@ -649,7 +639,7 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement private int getVtableIndexForInterfaceMethod(ResolvedJavaType resolved) { HotSpotResolvedObjectTypeImpl hotspotType = (HotSpotResolvedObjectTypeImpl) resolved; - return runtime().getCompilerToVM().getVtableIndexForInterfaceMethod(hotspotType, this); + return compilerToVM().getVtableIndexForInterfaceMethod(hotspotType, this); } /** @@ -682,14 +672,14 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement } public int intrinsicId() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); return UNSAFE.getChar(metaspaceMethod + config.methodIntrinsicIdOffset); } @Override public JavaConstant invoke(JavaConstant receiver, JavaConstant[] arguments) { - assert!isConstructor(); - Method javaMethod = toJava(); + assert !isConstructor(); + Method javaMethod = (Method) toJava(); javaMethod.setAccessible(true); Object[] objArguments = new Object[arguments.length]; @@ -714,13 +704,13 @@ public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implement * @return compile id */ public int allocateCompileId(int entryBCI) { - return runtime().getCompilerToVM().allocateCompileId(this, entryBCI); + return compilerToVM().allocateCompileId(this, entryBCI); } public boolean hasCodeAtLevel(int entryBCI, int level) { - if (entryBCI == runtime().getConfig().invocationEntryBci) { + if (entryBCI == config().invocationEntryBci) { return hasCompiledCodeAtLevel(level); } - return runtime().getCompilerToVM().hasCompiledCodeForOSR(this, entryBCI, level); + return compilerToVM().hasCompiledCodeForOSR(this, entryBCI, level); } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java index 365ff70b11e..cba1ee3154b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 @@ -22,11 +22,11 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ResolvedJavaType; public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType { - public HotSpotResolvedJavaType(String name) { + HotSpotResolvedJavaType(String name) { super(name); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index 18c04ece6bc..3501387061b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -22,14 +22,30 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.meta.Assumptions.*; +import jdk.vm.ci.meta.Assumptions.AssumptionResult; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes. */ public interface HotSpotResolvedObjectType extends ResolvedJavaType { + /** + * Gets the JVMCI mirror for a {@link Class} object. + * + * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass} + */ + static HotSpotResolvedObjectType fromObjectClass(Class javaClass) { + return HotSpotResolvedObjectTypeImpl.fromObjectClass(javaClass); + } + HotSpotResolvedObjectType getArrayClass(); ResolvedJavaType getComponentType(); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 735ff43f4eb..4ef227ec823 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -22,24 +22,44 @@ */ package jdk.vm.ci.hotspot; -import static java.util.Objects.*; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*; +import static java.util.Objects.requireNonNull; +import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.net.*; -import java.nio.*; -import java.util.*; +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.meta.Assumptions.*; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.Assumptions.AssumptionResult; +import jdk.vm.ci.meta.Assumptions.ConcreteMethod; +import jdk.vm.ci.meta.Assumptions.ConcreteSubtype; +import jdk.vm.ci.meta.Assumptions.LeafType; +import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MetaUtil; +import jdk.vm.ci.meta.ModifiersProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.TrustedInterface; /** * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes. */ -public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, HotSpotProxified, MetaspaceWrapperObject { +final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, HotSpotProxified, MetaspaceWrapperObject { /** * The Java class this type represents. @@ -58,7 +78,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType * * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass} */ - public static HotSpotResolvedObjectTypeImpl fromObjectClass(Class javaClass) { + static HotSpotResolvedObjectTypeImpl fromObjectClass(Class javaClass) { return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(javaClass); } @@ -108,11 +128,11 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType /** * Gets the metaspace Klass for this type. */ - public long getMetaspaceKlass() { + long getMetaspaceKlass() { if (HotSpotJVMCIRuntime.getHostWordKind() == JavaKind.Long) { - return UNSAFE.getLong(javaClass, (long) runtime().getConfig().klassOffset); + return UNSAFE.getLong(javaClass, (long) config().klassOffset); } - return UNSAFE.getInt(javaClass, (long) runtime().getConfig().klassOffset) & 0xFFFFFFFFL; + return UNSAFE.getInt(javaClass, (long) config().klassOffset) & 0xFFFFFFFFL; } public long getMetaspacePointer() { @@ -129,7 +149,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType } public int getAccessFlags() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset); } @@ -149,7 +169,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType @Override public AssumptionResult findLeafConcreteSubtype() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); if (isArray()) { return getElementalType().isLeaf() ? new AssumptionResult<>(this) : null; } else if (isInterface()) { @@ -214,7 +234,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType * @return value of the subklass field as metaspace klass pointer */ private HotSpotResolvedObjectTypeImpl getSubklass() { - return runtime().getCompilerToVM().getResolvedJavaType(this, runtime().getConfig().subklassOffset, false); + return compilerToVM().getResolvedJavaType(this, config().subklassOffset, false); } @Override @@ -241,7 +261,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType if (!isInterface()) { throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this); } - return runtime().getCompilerToVM().getImplementor(this); + return compilerToVM().getImplementor(this); } public HotSpotResolvedObjectTypeImpl getSupertype() { @@ -289,14 +309,14 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType } @Override - public JavaConstant getObjectHub() { + public Constant getObjectHub() { return klass(); } @Override public AssumptionResult hasFinalizableSubclass() { assert !isArray(); - if (!runtime().getCompilerToVM().hasFinalizableSubclass(this)) { + if (!compilerToVM().hasFinalizableSubclass(this)) { return new AssumptionResult<>(false, new NoFinalizableSubclass(this)); } return new AssumptionResult<>(true); @@ -304,7 +324,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType @Override public boolean hasFinalizer() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); return (getAccessFlags() & config.klassHasFinalizerFlag) != 0; } @@ -320,12 +340,12 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType @Override public boolean isInitialized() { - return isArray() ? true : getInitState() == runtime().getConfig().instanceKlassStateFullyInitialized; + return isArray() ? true : getInitState() == config().instanceKlassStateFullyInitialized; } @Override public boolean isLinked() { - return isArray() ? true : getInitState() >= runtime().getConfig().instanceKlassStateLinked; + return isArray() ? true : getInitState() >= config().instanceKlassStateLinked; } /** @@ -336,7 +356,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType */ private int getInitState() { assert !isArray() : "_init_state only exists in InstanceKlass"; - return UNSAFE.getByte(getMetaspaceKlass() + runtime().getConfig().instanceKlassInitStateOffset) & 0xFF; + return UNSAFE.getByte(getMetaspaceKlass() + config().instanceKlassInitStateOffset) & 0xFF; } @Override @@ -405,12 +425,12 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType } HotSpotResolvedJavaMethodImpl hotSpotMethod = (HotSpotResolvedJavaMethodImpl) method; HotSpotResolvedObjectTypeImpl hotSpotCallerType = (HotSpotResolvedObjectTypeImpl) callerType; - return runtime().getCompilerToVM().resolveMethod(this, hotSpotMethod, hotSpotCallerType); + return compilerToVM().resolveMethod(this, hotSpotMethod, hotSpotCallerType); } public HotSpotConstantPool getConstantPool() { if (constantPool == null) { - constantPool = runtime().getCompilerToVM().getConstantPool(this, runtime().getConfig().instanceKlassConstantsOffset); + constantPool = compilerToVM().getConstantPool(this, config().instanceKlassConstantsOffset); } return constantPool; } @@ -424,7 +444,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType assert !isArray(); assert !isInterface(); - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); final int layoutHelper = layoutHelper(); assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance"; @@ -438,7 +458,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType } public int layoutHelper() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset); } @@ -458,7 +478,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType } public int getVtableLength() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); if (isInterface() || isArray()) { /* Everything has the core vtable of java.lang.Object */ return config.baseVtableLength(); @@ -547,7 +567,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType * @param index index to the fields array */ public FieldInfo(int index) { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); // Get Klass::_fields final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset); assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code"; @@ -555,19 +575,19 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType } private int getAccessFlags() { - return readFieldSlot(runtime().getConfig().fieldInfoAccessFlagsOffset); + return readFieldSlot(config().fieldInfoAccessFlagsOffset); } private int getNameIndex() { - return readFieldSlot(runtime().getConfig().fieldInfoNameIndexOffset); + return readFieldSlot(config().fieldInfoNameIndexOffset); } private int getSignatureIndex() { - return readFieldSlot(runtime().getConfig().fieldInfoSignatureIndexOffset); + return readFieldSlot(config().fieldInfoSignatureIndexOffset); } public int getOffset() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); final int lowPacked = readFieldSlot(config.fieldInfoLowPackedOffset); final int highPacked = readFieldSlot(config.fieldInfoHighPackedOffset); final int offset = ((highPacked << Short.SIZE) | lowPacked) >> config.fieldInfoTagSize; @@ -606,7 +626,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType } private boolean isInternal() { - return (getAccessFlags() & runtime().getConfig().jvmAccFieldInternal) != 0; + return (getAccessFlags() & config().jvmAccFieldInternal) != 0; } public boolean isStatic() { @@ -614,7 +634,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType } public boolean hasGenericSignature() { - return (getAccessFlags() & runtime().getConfig().jvmAccFieldHasGenericSignature) != 0; + return (getAccessFlags() & config().jvmAccFieldHasGenericSignature) != 0; } } @@ -707,7 +727,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType * See {@code FieldStreamBase::init_generic_signature_start_slot} */ private int getFieldCount() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset); int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset); int fieldCount = 0; @@ -729,7 +749,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType @Override public String getSourceFileName() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset); if (sourceFileNameIndex == 0) { return null; @@ -784,21 +804,21 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType /** * Gets the metaspace Klass boxed in a {@link JavaConstant}. */ - public JavaConstant klass() { - return HotSpotMetaspaceConstantImpl.forMetaspaceObject(runtime().getHostJVMCIBackend().getTarget().wordKind, getMetaspaceKlass(), this, false); + public Constant klass() { + return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false); } public boolean isPrimaryType() { - return runtime().getConfig().secondarySuperCacheOffset != superCheckOffset(); + return config().secondarySuperCacheOffset != superCheckOffset(); } public int superCheckOffset() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); return UNSAFE.getInt(getMetaspaceKlass() + config.superCheckOffsetOffset); } public long prototypeMarkWord() { - HotSpotVMConfig config = runtime().getConfig(); + HotSpotVMConfig config = config(); if (isArray()) { return config.arrayPrototypeMarkWord(); } else { @@ -874,7 +894,7 @@ public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType } public ResolvedJavaMethod getClassInitializer() { - return runtime().getCompilerToVM().getClassInitializer(this); + return compilerToVM().getClassInitializer(this); } @Override diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index 7d0491553f9..7a8f3e8a633 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -22,15 +22,21 @@ */ package jdk.vm.ci.hotspot; -import static java.util.Objects.*; +import static java.util.Objects.requireNonNull; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.net.*; +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.lang.reflect.Modifier; +import java.net.URL; -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.meta.Assumptions.AssumptionResult; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Implementation of {@link JavaType} for primitive HotSpot types. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java new file mode 100644 index 00000000000..5ec69e5819a --- /dev/null +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011, 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.vm.ci.hotspot; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.InvalidInstalledCodeException; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * Implementation of {@link InstalledCode} for code installed as a RuntimeStub. + */ +public class HotSpotRuntimeStub extends HotSpotInstalledCode { + + public HotSpotRuntimeStub(String name) { + super(name); + } + + public ResolvedJavaMethod getMethod() { + return null; + } + + @Override + public boolean isValid() { + return true; + } + + @Override + public void invalidate() { + } + + @Override + public String toString() { + return String.format("InstalledRuntimeStub[stub=%s, codeBlob=0x%x]", name, getAddress()); + } + + @Override + public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { + throw new InternalError("Cannot call stub " + name); + } +} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSentinelConstant.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSentinelConstant.java index 0ce340d12ac..76cd07a3979 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSentinelConstant.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSentinelConstant.java @@ -22,16 +22,23 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.LIRKind; +import jdk.vm.ci.meta.VMConstant; +import jdk.vm.ci.meta.Value; public final class HotSpotSentinelConstant extends Value implements JavaConstant, VMConstant { - public HotSpotSentinelConstant(JavaKind kind) { - super(LIRKind.reference(kind)); + private final JavaKind javaKind; + + public HotSpotSentinelConstant(LIRKind lirKind, JavaKind javaKind) { + super(lirKind); + this.javaKind = javaKind; } public JavaKind getJavaKind() { - return (JavaKind) getLIRKind().getPlatformKind(); + return javaKind; } @Override diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java index 5d873e9ac95..c6ad02a311f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java @@ -22,10 +22,14 @@ */ package jdk.vm.ci.hotspot; -import java.util.*; +import java.util.ArrayList; +import java.util.List; -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; /** * Represents a method signature. @@ -131,7 +135,7 @@ public class HotSpotSignature implements Signature { JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0)); return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(kind.toJavaClass()); } - return new HotSpotUnresolvedJavaType(name, runtime); + return HotSpotUnresolvedJavaType.create(runtime, name); } @Override diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java index 0f9c7a05ac3..e619fb45ee7 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java @@ -22,13 +22,63 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; -public class HotSpotSpeculationLog extends SpeculationLog { +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.SpeculationLog; + +public class HotSpotSpeculationLog implements SpeculationLog { + + /** Written by the C++ code that performs deoptimization. */ + private volatile Object lastFailed; + + /** All speculations that have been a deoptimization reason. */ + private Set failedSpeculations; + + /** Strong references to all reasons embededded in the current nmethod. */ + private volatile Collection speculations; @Override - public JavaConstant speculate(Object reason) { - addSpeculation(reason); + public synchronized void collectFailedSpeculations() { + if (lastFailed != null) { + if (failedSpeculations == null) { + failedSpeculations = new HashSet<>(2); + } + failedSpeculations.add((SpeculationReason) lastFailed); + lastFailed = null; + speculations = null; + } + } + + @Override + public boolean maySpeculate(SpeculationReason reason) { + if (failedSpeculations != null && failedSpeculations.contains(reason)) { + return false; + } + return true; + } + + @Override + public JavaConstant speculate(SpeculationReason reason) { + assert maySpeculate(reason); + + /* + * Objects referenced from nmethods are weak references. We need a strong reference to the + * reason objects that are embedded in nmethods, so we add them to the speculations + * collection. + */ + if (speculations == null) { + synchronized (this) { + if (speculations == null) { + speculations = new ConcurrentLinkedQueue<>(); + } + } + } + speculations.add(reason); + return HotSpotObjectConstantImpl.forObject(reason); } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java index 5ece48ac8dc..b40ba20ac4d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java @@ -22,10 +22,10 @@ */ package jdk.vm.ci.hotspot; -import java.util.*; +import java.util.Arrays; -import jdk.vm.ci.code.stack.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.stack.InspectedFrame; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class HotSpotStackFrameReference implements InspectedFrame { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackIntrospection.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackIntrospection.java new file mode 100644 index 00000000000..9a7751d6fad --- /dev/null +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackIntrospection.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 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.vm.ci.hotspot; + +import jdk.vm.ci.code.stack.InspectedFrameVisitor; +import jdk.vm.ci.code.stack.StackIntrospection; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class HotSpotStackIntrospection implements StackIntrospection { + + protected final HotSpotJVMCIRuntimeProvider runtime; + + public HotSpotStackIntrospection(HotSpotJVMCIRuntimeProvider runtime) { + this.runtime = runtime; + } + + @Override + public T iterateFrames(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip, InspectedFrameVisitor visitor) { + CompilerToVM compilerToVM = runtime.getCompilerToVM(); + HotSpotStackFrameReference current = compilerToVM.getNextStackFrame(null, initialMethods, initialSkip); + while (current != null) { + T result = visitor.visitFrame(current); + if (result != null) { + return result; + } + current = compilerToVM.getNextStackFrame(current, matchingMethods, 0); + } + return null; + } +} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedField.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedField.java index 45fd7b9df44..d1ef070e39d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedField.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, 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 @@ -22,18 +22,19 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaField; +import jdk.vm.ci.meta.JavaType; /** * A implementation of {@link JavaField} for an unresolved field. */ -public class HotSpotUnresolvedField implements JavaField { +class HotSpotUnresolvedField implements JavaField { private final String name; private final JavaType holder; private final JavaType type; - public HotSpotUnresolvedField(JavaType holder, String name, JavaType type) { + HotSpotUnresolvedField(JavaType holder, String name, JavaType type) { this.name = name; this.type = type; this.holder = holder; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedJavaType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedJavaType.java index 1e945d48de1..d9e3390df3a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedJavaType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedJavaType.java @@ -22,16 +22,18 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Implementation of {@link JavaType} for unresolved HotSpot classes. */ -public class HotSpotUnresolvedJavaType extends HotSpotJavaType { +final class HotSpotUnresolvedJavaType extends HotSpotJavaType { private final HotSpotJVMCIRuntimeProvider runtime; - public HotSpotUnresolvedJavaType(String name, HotSpotJVMCIRuntimeProvider runtime) { + private HotSpotUnresolvedJavaType(String name, HotSpotJVMCIRuntimeProvider runtime) { super(name); assert name.charAt(0) == '[' || name.charAt(name.length() - 1) == ';' : name; this.runtime = runtime; @@ -40,7 +42,7 @@ public class HotSpotUnresolvedJavaType extends HotSpotJavaType { /** * Creates an unresolved type for a valid {@link JavaType#getName() type name}. */ - public static HotSpotUnresolvedJavaType create(HotSpotJVMCIRuntimeProvider runtime, String name) { + static HotSpotUnresolvedJavaType create(HotSpotJVMCIRuntimeProvider runtime, String name) { return new HotSpotUnresolvedJavaType(name, runtime); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index f5cbf2f6de1..7b924e25ed9 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -23,14 +23,23 @@ package jdk.vm.ci.hotspot; import static jdk.vm.ci.common.UnsafeUtil.readCString; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Iterator; -import sun.misc.*; -import jdk.vm.ci.common.*; -import jdk.vm.ci.hotspotvmconfig.*; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.hotspotvmconfig.HotSpotVMAddress; +import jdk.vm.ci.hotspotvmconfig.HotSpotVMConstant; +import jdk.vm.ci.hotspotvmconfig.HotSpotVMData; +import jdk.vm.ci.hotspotvmconfig.HotSpotVMField; +import jdk.vm.ci.hotspotvmconfig.HotSpotVMFlag; +import jdk.vm.ci.hotspotvmconfig.HotSpotVMManual; +import jdk.vm.ci.hotspotvmconfig.HotSpotVMType; +import sun.misc.Unsafe; //JaCoCo Exclude @@ -41,6 +50,13 @@ import jdk.vm.ci.hotspotvmconfig.*; */ public class HotSpotVMConfig { + /** + * Gets the configuration associated with the singleton {@link HotSpotJVMCIRuntime}. + */ + public static HotSpotVMConfig config() { + return runtime().getConfig(); + } + /** * Maximum allowed size of allocated area for a frame. */ @@ -48,7 +64,7 @@ public class HotSpotVMConfig { public HotSpotVMConfig(CompilerToVM compilerToVm) { // Get raw pointer to the array that contains all gHotSpotVM values. - final long gHotSpotVMData = compilerToVm.initializeConfiguration(); + final long gHotSpotVMData = compilerToVm.initializeConfiguration(this); assert gHotSpotVMData != 0; // Make FindBugs happy. @@ -106,6 +122,8 @@ public class HotSpotVMConfig { handleDeoptStub = deoptBlob + UNSAFE.getInt(deoptBlob + codeBlobCodeOffsetOffset) + UNSAFE.getInt(deoptBlob + deoptimizationBlobUnpackOffsetOffset); uncommonTrapStub = deoptBlob + UNSAFE.getInt(deoptBlob + codeBlobCodeOffsetOffset) + UNSAFE.getInt(deoptBlob + deoptimizationBlobUncommonTrapOffsetOffset); + tlabAlignmentReserve = roundUp(threadLocalAllocBufferEndReserve(), minObjAlignment()); + assert check(); assert HotSpotVMConfigVerifier.check(); } @@ -844,6 +862,7 @@ public class HotSpotVMConfig { @HotSpotVMConstant(name = "ASSERT") @Stable public boolean cAssertions; public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows"); + public final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux"); @HotSpotVMFlag(name = "CodeEntryAlignment") @Stable public int codeEntryAlignment; @HotSpotVMFlag(name = "VerifyOops") @Stable public boolean verifyOops; @@ -938,6 +957,16 @@ public class HotSpotVMConfig { @HotSpotVMConstant(name = "VM_Version::CPU_ERMS", archs = {"amd64"}) @Stable public long cpuERMS; @HotSpotVMConstant(name = "VM_Version::CPU_CLMUL", archs = {"amd64"}) @Stable public long cpuCLMUL; @HotSpotVMConstant(name = "VM_Version::CPU_BMI1", archs = {"amd64"}) @Stable public long cpuBMI1; + @HotSpotVMConstant(name = "VM_Version::CPU_BMI2", archs = {"amd64"}) @Stable public long cpuBMI2; + @HotSpotVMConstant(name = "VM_Version::CPU_RTM", archs = {"amd64"}) @Stable public long cpuRTM; + @HotSpotVMConstant(name = "VM_Version::CPU_ADX", archs = {"amd64"}) @Stable public long cpuADX; + @HotSpotVMConstant(name = "VM_Version::CPU_AVX512F", archs = {"amd64"}) @Stable public long cpuAVX512F; + @HotSpotVMConstant(name = "VM_Version::CPU_AVX512DQ", archs = {"amd64"}) @Stable public long cpuAVX512DQ; + @HotSpotVMConstant(name = "VM_Version::CPU_AVX512PF", archs = {"amd64"}) @Stable public long cpuAVX512PF; + @HotSpotVMConstant(name = "VM_Version::CPU_AVX512ER", archs = {"amd64"}) @Stable public long cpuAVX512ER; + @HotSpotVMConstant(name = "VM_Version::CPU_AVX512CD", archs = {"amd64"}) @Stable public long cpuAVX512CD; + @HotSpotVMConstant(name = "VM_Version::CPU_AVX512BW", archs = {"amd64"}) @Stable public long cpuAVX512BW; + @HotSpotVMConstant(name = "VM_Version::CPU_AVX512VL", archs = {"amd64"}) @Stable public long cpuAVX512VL; // SPARC specific values @HotSpotVMField(name = "VM_Version::_features", type = "int", get = HotSpotVMField.Type.VALUE, archs = {"sparc"}) @Stable public int sparcFeatures; @@ -945,6 +974,26 @@ public class HotSpotVMConfig { @HotSpotVMConstant(name = "VM_Version::vis2_instructions_m", archs = {"sparc"}) @Stable public int vis2Instructions; @HotSpotVMConstant(name = "VM_Version::vis1_instructions_m", archs = {"sparc"}) @Stable public int vis1Instructions; @HotSpotVMConstant(name = "VM_Version::cbcond_instructions_m", archs = {"sparc"}) @Stable public int cbcondInstructions; + @HotSpotVMConstant(name = "VM_Version::v8_instructions_m", archs = {"sparc"}) @Stable public int v8Instructions; + @HotSpotVMConstant(name = "VM_Version::hardware_mul32_m", archs = {"sparc"}) @Stable public int hardwareMul32; + @HotSpotVMConstant(name = "VM_Version::hardware_div32_m", archs = {"sparc"}) @Stable public int hardwareDiv32; + @HotSpotVMConstant(name = "VM_Version::hardware_fsmuld_m", archs = {"sparc"}) @Stable public int hardwareFsmuld; + @HotSpotVMConstant(name = "VM_Version::hardware_popc_m", archs = {"sparc"}) @Stable public int hardwarePopc; + @HotSpotVMConstant(name = "VM_Version::v9_instructions_m", archs = {"sparc"}) @Stable public int v9Instructions; + @HotSpotVMConstant(name = "VM_Version::sun4v_m", archs = {"sparc"}) @Stable public int sun4v; + @HotSpotVMConstant(name = "VM_Version::blk_init_instructions_m", archs = {"sparc"}) @Stable public int blkInitInstructions; + @HotSpotVMConstant(name = "VM_Version::fmaf_instructions_m", archs = {"sparc"}) @Stable public int fmafInstructions; + @HotSpotVMConstant(name = "VM_Version::fmau_instructions_m", archs = {"sparc"}) @Stable public int fmauInstructions; + @HotSpotVMConstant(name = "VM_Version::sparc64_family_m", archs = {"sparc"}) @Stable public int sparc64Family; + @HotSpotVMConstant(name = "VM_Version::M_family_m", archs = {"sparc"}) @Stable public int mFamily; + @HotSpotVMConstant(name = "VM_Version::T_family_m", archs = {"sparc"}) @Stable public int tFamily; + @HotSpotVMConstant(name = "VM_Version::T1_model_m", archs = {"sparc"}) @Stable public int t1Model; + @HotSpotVMConstant(name = "VM_Version::sparc5_instructions_m", archs = {"sparc"}) @Stable public int sparc5Instructions; + @HotSpotVMConstant(name = "VM_Version::aes_instructions_m", archs = {"sparc"}) @Stable public int aesInstructions; + @HotSpotVMConstant(name = "VM_Version::sha1_instruction_m", archs = {"sparc"}) @Stable public int sha1Instruction; + @HotSpotVMConstant(name = "VM_Version::sha256_instruction_m", archs = {"sparc"}) @Stable public int sha256Instruction; + @HotSpotVMConstant(name = "VM_Version::sha512_instruction_m", archs = {"sparc"}) @Stable public int sha512Instruction; + @HotSpotVMFlag(name = "UseBlockZeroing", archs = {"sparc"}) @Stable public boolean useBlockZeroing; @HotSpotVMFlag(name = "BlockZeroingLowLimit", archs = {"sparc"}) @Stable public int blockZeroingLowLimit; @@ -1063,7 +1112,7 @@ public class HotSpotVMConfig { @HotSpotVMField(name = "JavaThread::_osthread", type = "OSThread*", get = HotSpotVMField.Type.OFFSET) @Stable public int osThreadOffset; @HotSpotVMField(name = "JavaThread::_dirty_card_queue", type = "DirtyCardQueue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadDirtyCardQueueOffset; @HotSpotVMField(name = "JavaThread::_is_method_handle_return", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int threadIsMethodHandleReturnOffset; - @HotSpotVMField(name = "JavaThread::_satb_mark_queue", type = "ObjPtrQueue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadSatbMarkQueueOffset; + @HotSpotVMField(name = "JavaThread::_satb_mark_queue", type = "SATBMarkQueue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadSatbMarkQueueOffset; @HotSpotVMField(name = "JavaThread::_vm_result", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectResultOffset; @HotSpotVMField(name = "JavaThread::_jvmci_counters", type = "jlong*", get = HotSpotVMField.Type.OFFSET) @Stable public int jvmciCountersThreadOffset; @@ -1396,6 +1445,7 @@ public class HotSpotVMConfig { @HotSpotVMField(name = "Thread::_allocated_bytes", type = "jlong", get = HotSpotVMField.Type.OFFSET) @Stable public int threadAllocatedBytesOffset; @HotSpotVMFlag(name = "TLABWasteIncrement") @Stable public int tlabRefillWasteIncrement; + @HotSpotVMManual(name = "ThreadLocalAllocBuffer::alignment_reserve()") @Stable public int tlabAlignmentReserve; @HotSpotVMField(name = "ThreadLocalAllocBuffer::_start", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferStartOffset; @HotSpotVMField(name = "ThreadLocalAllocBuffer::_end", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferEndOffset; @@ -1453,13 +1503,6 @@ public class HotSpotVMConfig { return Integer.max(reserveSize, abstractVmVersionReserveForAllocationPrefetch); } - /** - * See: {@code ThreadLocalAllocBuffer::alignment_reserve()}. - */ - public final int tlabAlignmentReserve() { - return roundUp(threadLocalAllocBufferEndReserve(), minObjAlignment()); - } - @HotSpotVMFlag(name = "TLABStats") @Stable public boolean tlabStats; // FIXME This is only temporary until the GC code is changed. @@ -1688,6 +1731,7 @@ public class HotSpotVMConfig { @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_NEAR") @Stable public int MARKID_POLL_RETURN_NEAR; @HotSpotVMConstant(name = "CodeInstaller::POLL_FAR") @Stable public int MARKID_POLL_FAR; @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_FAR") @Stable public int MARKID_POLL_RETURN_FAR; + @HotSpotVMConstant(name = "CodeInstaller::CARD_TABLE_SHIFT") @Stable public int MARKID_CARD_TABLE_SHIFT; @HotSpotVMConstant(name = "CodeInstaller::CARD_TABLE_ADDRESS") @Stable public int MARKID_CARD_TABLE_ADDRESS; @HotSpotVMConstant(name = "CodeInstaller::HEAP_TOP_ADDRESS") @Stable public int MARKID_HEAP_TOP_ADDRESS; @HotSpotVMConstant(name = "CodeInstaller::HEAP_END_ADDRESS") @Stable public int MARKID_HEAP_END_ADDRESS; @@ -1695,6 +1739,20 @@ public class HotSpotVMConfig { @HotSpotVMConstant(name = "CodeInstaller::CRC_TABLE_ADDRESS") @Stable public int MARKID_CRC_TABLE_ADDRESS; @HotSpotVMConstant(name = "CodeInstaller::INVOKE_INVALID") @Stable public int MARKID_INVOKE_INVALID; + @HotSpotVMConstant(name = "BitData::exception_seen_flag") @Stable public int bitDataExceptionSeenFlag; + @HotSpotVMConstant(name = "BitData::null_seen_flag") @Stable public int bitDataNullSeenFlag; + @HotSpotVMConstant(name = "CounterData::count_off") @Stable public int methodDataCountOffset; + @HotSpotVMConstant(name = "JumpData::taken_off_set") @Stable public int jumpDataTakenOffset; + @HotSpotVMConstant(name = "JumpData::displacement_off_set") @Stable public int jumpDataDisplacementOffset; + @HotSpotVMConstant(name = "ReceiverTypeData::nonprofiled_count_off_set") @Stable public int receiverTypeDataNonprofiledCountOffset; + @HotSpotVMConstant(name = "ReceiverTypeData::receiver_type_row_cell_count") @Stable public int receiverTypeDataReceiverTypeRowCellCount; + @HotSpotVMConstant(name = "ReceiverTypeData::receiver0_offset") @Stable public int receiverTypeDataReceiver0Offset; + @HotSpotVMConstant(name = "ReceiverTypeData::count0_offset") @Stable public int receiverTypeDataCount0Offset; + @HotSpotVMConstant(name = "BranchData::not_taken_off_set") @Stable public int branchDataNotTakenOffset; + @HotSpotVMConstant(name = "ArrayData::array_len_off_set") @Stable public int arrayDataArrayLenOffset; + @HotSpotVMConstant(name = "ArrayData::array_start_off_set") @Stable public int arrayDataArrayStartOffset; + @HotSpotVMConstant(name = "MultiBranchData::per_case_cell_count") @Stable public int multiBranchDataPerCaseCellCount; + // Checkstyle: resume private boolean check() { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java index 3a449db38b0..5f82244d055 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java @@ -22,16 +22,25 @@ */ package jdk.vm.ci.hotspot; -import static java.lang.String.*; +import static java.lang.String.format; -import java.io.*; -import java.lang.reflect.*; -import java.util.*; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Objects; -import jdk.internal.org.objectweb.asm.*; +import jdk.vm.ci.common.JVMCIError; +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.Label; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; -import jdk.vm.ci.common.*; -import sun.misc.*; +import sun.misc.Unsafe; /** * A {@link ClassVisitor} that verifies {@link HotSpotVMConfig} does not access {@link Unsafe} from diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMEventListener.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMEventListener.java index 520a3da4cc9..c9d3db7ef09 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMEventListener.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMEventListener.java @@ -22,8 +22,10 @@ */ package jdk.vm.ci.hotspot; -import jdk.vm.ci.code.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.CompilationResult; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.meta.JVMCIMetaAccessContext; +import jdk.vm.ci.meta.ResolvedJavaType; public interface HotSpotVMEventListener { @@ -34,7 +36,7 @@ public interface HotSpotVMEventListener { } /** - * Notify on successful install into the CodeCache. + * Notify on successful install into the code cache. * * @param hotSpotCodeCacheProvider * @param installedCode @@ -43,14 +45,6 @@ public interface HotSpotVMEventListener { default void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompilationResult compResult) { } - /** - * Perform any extra initialization required. - * - * @param runtime - */ - default void completeInitialization(HotSpotJVMCIRuntime runtime) { - } - /** * Create a custom {@link JVMCIMetaAccessContext} to be used for managing the lifetime of loaded * metadata. It a custom one isn't created then the default implementation will be a single diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java index 8c06c321ace..0e1398eeaea 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -22,15 +22,14 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; - -import sun.misc.*; +import sun.misc.Unsafe; /** * Class to access the C++ {@code vmSymbols} table. */ -public final class HotSpotVmSymbols { +final class HotSpotVmSymbols { /** * Returns the symbol in the {@code vmSymbols} table at position {@code index} as {@link String} @@ -39,7 +38,7 @@ public final class HotSpotVmSymbols { * @param index position in the symbol table * @return the symbol at position id */ - public static String symbolAt(int index) { + static String symbolAt(int index) { HotSpotJVMCIRuntimeProvider runtime = runtime(); HotSpotVMConfig config = runtime.getConfig(); assert config.vmSymbolsFirstSID <= index && index < config.vmSymbolsSIDLimit : "index " + index + " is out of bounds"; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java index d1df11f0eb1..444b25bed3d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ package jdk.vm.ci.hotspot; * It would preferable if this were the base class containing the pointer but that would require * mixins since most of the wrapper types have complex supertype hierarchies. */ -public interface MetaspaceWrapperObject { +interface MetaspaceWrapperObject { long getMetaspacePointer(); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Stable.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Stable.java index 2cda0c24241..e386dc0ca77 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Stable.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Stable.java @@ -23,11 +23,14 @@ package jdk.vm.ci.hotspot; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** - * This annotation functions as an alias for the sun.invoke.Stable annotation within JVMCI code. It - * is specially recognized during class file parsing in the same way as that annotation. + * This annotation functions as an alias for the java.lang.invoke.Stable annotation within JVMCI + * code. It is specially recognized during class file parsing in the same way as that annotation. */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/events/EmptyEventProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/events/EmptyEventProvider.java index 9e5df8268db..8e39f7191f1 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/events/EmptyEventProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/events/EmptyEventProvider.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.hotspot.events; -import jdk.vm.ci.common.*; +import jdk.vm.ci.common.JVMCIError; /** * An empty implementation for {@link EventProvider}. This implementation is used when no logging is diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMAddress.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMAddress.java index 4e810f9bedd..0900bfa207d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMAddress.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMAddress.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.hotspotvmconfig; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Refers to a C++ address in the VM. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMConstant.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMConstant.java index bf8a465f52f..10da8b6ecdd 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMConstant.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMConstant.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.hotspotvmconfig; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Refers to a C++ constant in the VM. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMData.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMData.java index 7cf45a51c0f..f993fd620ee 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMData.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMData.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.hotspotvmconfig; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Refers to a entry in {@code gHotSpotVMData}. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMField.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMField.java index 158a6879309..c58c9e72fd5 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMField.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMField.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.hotspotvmconfig; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Refers to a C++ field in the VM. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMFlag.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMFlag.java index d8b5d3e13de..99e9ac39fb2 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMFlag.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMFlag.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.hotspotvmconfig; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Refers to a C++ flag in the VM. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMManual.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMManual.java index 7aed441a2d6..91ddf950879 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMManual.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMManual.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.hotspotvmconfig; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Annotates a field in HotSpotVMConfig which is not read from the VM but is calculated manually. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMType.java index 4e22c3948da..1be06f15630 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMType.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.hotspotvmconfig; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Refers to a C++ type in the VM. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java index f90e9fa33ff..dbbc950d6b2 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java @@ -22,8 +22,12 @@ */ package jdk.vm.ci.meta; -import java.lang.invoke.*; -import java.util.*; +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; /** * Class for recording assumptions made during compilation. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantReflectionProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantReflectionProvider.java index 6e130abb446..1db2b98c7ea 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantReflectionProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantReflectionProvider.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import java.lang.invoke.*; +import java.lang.invoke.MethodHandle; /** * Reflection operations on values represented as {@linkplain JavaConstant constants}. All methods @@ -142,8 +142,12 @@ public interface ConstantReflectionProvider { /** * Check if the constant is embeddable in the code. + * + * @param constant the constant to test */ - boolean isEmbeddable(Constant constant); + default boolean isEmbeddable(Constant constant) { + return true; + } /** * Gets access to the internals of {@link MethodHandle}. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DefaultProfilingInfo.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DefaultProfilingInfo.java index f5a9979a4ba..3157d3cac14 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DefaultProfilingInfo.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DefaultProfilingInfo.java @@ -93,7 +93,7 @@ public final class DefaultProfilingInfo implements ProfilingInfo { @Override public String toString() { - return "BaseProfilingInfo<" + this.toString(null, "; ") + ">"; + return "DefaultProfilingInfo<" + this.toString(null, "; ") + ">"; } public void setMature() { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ExceptionHandler.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ExceptionHandler.java index 8b03551ee8b..4beae9daa05 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ExceptionHandler.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ExceptionHandler.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import java.util.*; +import java.util.Objects; /** * Represents an exception handler within the bytecodes. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JVMCIMetaAccessContext.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JVMCIMetaAccessContext.java index 6af1dac11c5..f44c061f764 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JVMCIMetaAccessContext.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JVMCIMetaAccessContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaField.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaField.java index dcf965c03a0..73ab3f5680c 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaField.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaField.java @@ -22,7 +22,8 @@ */ package jdk.vm.ci.meta; -import java.util.*; +import java.util.IllegalFormatException; +import java.util.UnknownFormatConversionException; /** * Represents a reference to a Java field, either resolved or unresolved fields. Fields, like @@ -77,7 +78,6 @@ public interface JavaField extends TrustedInterface { * @return the result of formatting this field according to {@code format} * @throws IllegalFormatException if an illegal specifier is encountered in {@code format} */ - @SuppressWarnings("fallthrough") default String format(String format) throws IllegalFormatException { StringBuilder sb = new StringBuilder(); int index = 0; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java index 2b2139097a4..bd8df8299c2 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import java.lang.reflect.*; +import java.lang.reflect.Array; //JaCoCo Exclude @@ -31,7 +31,7 @@ import java.lang.reflect.*; * {@link JavaKind#Int} for {@code int} and {@link JavaKind#Object} for all object types. A kind has * a single character short name, a Java name, and a set of flags further describing its behavior. */ -public enum JavaKind implements PlatformKind { +public enum JavaKind { /** The primitive boolean kind, represented as an int on the stack. */ Boolean('z', "boolean", 1, true, java.lang.Boolean.TYPE, java.lang.Boolean.class), @@ -70,7 +70,6 @@ public enum JavaKind implements PlatformKind { private final boolean isStackInt; private final Class primitiveJavaClass; private final Class boxedJavaClass; - private final EnumKey key = new EnumKey<>(this); private final int slotCount; private JavaKind(char typeChar, String javaName, int slotCount, boolean isStackInt, Class primitiveJavaClass, Class boxedJavaClass) { @@ -113,10 +112,6 @@ public enum JavaKind implements PlatformKind { return javaName; } - public Key getKey() { - return key; - } - /** * Checks whether this type is a Java primitive type. * @@ -460,37 +455,4 @@ public enum JavaKind implements PlatformKind { throw new IllegalArgumentException("illegal call to bits on " + this); } } - - public JavaConstant getDefaultValue() { - switch (this) { - case Boolean: - return JavaConstant.FALSE; - case Int: - return JavaConstant.INT_0; - case Long: - return JavaConstant.LONG_0; - case Float: - return JavaConstant.FLOAT_0; - case Double: - return JavaConstant.DOUBLE_0; - case Object: - return JavaConstant.NULL_POINTER; - case Byte: - case Char: - case Short: - return new PrimitiveConstant(this, 0); - default: - throw new IllegalArgumentException("illegal call to getDefaultValue on " + this); - } - } - - @Override - public int getSizeInBytes() { - return getByteCount(); - } - - @Override - public int getVectorLength() { - return 1; - } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethod.java index 8244a1701d0..da61e58b027 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethod.java @@ -22,7 +22,8 @@ */ package jdk.vm.ci.meta; -import java.util.*; +import java.util.IllegalFormatException; +import java.util.UnknownFormatConversionException; /** * Represents a reference to a Java method, either resolved or unresolved. Methods, like fields and @@ -71,7 +72,6 @@ public interface JavaMethod extends TrustedInterface { * @return the result of formatting this method according to {@code format} * @throws IllegalFormatException if an illegal specifier is encountered in {@code format} */ - @SuppressWarnings("fallthrough") default String format(String format) throws IllegalFormatException { StringBuilder sb = new StringBuilder(); int index = 0; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethodProfile.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethodProfile.java index afa6ee3c7d2..f63c6f5a6d3 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethodProfile.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethodProfile.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import jdk.vm.ci.meta.JavaMethodProfile.*; +import jdk.vm.ci.meta.JavaMethodProfile.ProfiledMethod; /** * This profile object represents the method profile at a specific BCI. The precision of the diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaType.java index 4e3b20f69b0..9f5ff78f0a3 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaType.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import static jdk.vm.ci.meta.MetaUtil.*; +import static jdk.vm.ci.meta.MetaUtil.internalNameToJava; /** * Represents a resolved or unresolved type. Types include primitives, objects, {@code void}, and diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java index e76f70935d6..bafb822c86d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java @@ -22,9 +22,9 @@ */ package jdk.vm.ci.meta; -import java.util.*; +import java.util.ArrayList; -import jdk.vm.ci.meta.JavaTypeProfile.*; +import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType; /** * This profile object represents the type profile at a specific BCI. The precision of the supplied diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java index 9840aaa5367..220c17555c6 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import java.util.*; +import java.util.ArrayList; /** * Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the @@ -57,10 +57,32 @@ import java.util.*; */ public final class LIRKind { + private static enum IllegalKind implements PlatformKind { + ILLEGAL; + + private final EnumKey key = new EnumKey<>(this); + + public Key getKey() { + return key; + } + + public int getSizeInBytes() { + return 0; + } + + public int getVectorLength() { + return 0; + } + + public char getTypeChar() { + return '-'; + } + } + /** * The non-type. This uses {@link #unknownReference}, so it can never be part of an oop map. */ - public static final LIRKind Illegal = unknownReference(JavaKind.Illegal); + public static final LIRKind Illegal = unknownReference(IllegalKind.ILLEGAL); private final PlatformKind platformKind; private final int referenceMask; @@ -70,7 +92,6 @@ public final class LIRKind { private static final int UNKNOWN_REFERENCE = -1; private LIRKind(PlatformKind platformKind, int referenceMask, AllocatableValue derivedReferenceBase) { - assert platformKind != JavaKind.Object : "Kind.Object shouldn't be used in the backend"; this.platformKind = platformKind; this.referenceMask = referenceMask; this.derivedReferenceBase = derivedReferenceBase; @@ -431,21 +452,9 @@ public final class LIRKind { if (src.equals(dst)) { return true; } - /* - * TODO(je,rs) What we actually want is toStackKind(src.getPlatformKind()).equals( - * dst.getPlatformKind()) but due to the handling of sub-integer at the current point - * (phi-)moves from e.g. integer to short can happen. Therefore we compare stack kinds. - */ - if (toStackKind(src.getPlatformKind()).equals(toStackKind(dst.getPlatformKind()))) { + if (src.getPlatformKind().equals(dst.getPlatformKind())) { return !src.isUnknownReference() || dst.isUnknownReference(); } return false; } - - private static PlatformKind toStackKind(PlatformKind platformKind) { - if (platformKind instanceof JavaKind) { - return ((JavaKind) platformKind).getStackKind(); - } - return platformKind; - } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTableImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTableImpl.java index 68a652655ca..7cafe042a2a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTableImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTableImpl.java @@ -22,7 +22,8 @@ */ package jdk.vm.ci.meta; -import java.util.*; +import java.util.ArrayList; +import java.util.List; public class LocalVariableTableImpl implements LocalVariableTable { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocationIdentity.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocationIdentity.java index 3715ab4994e..b63b3dc740a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocationIdentity.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocationIdentity.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import java.util.*; +import java.util.IdentityHashMap; // JaCoCo Exclude diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java index 1c54ec5c5ea..5bc8f20a437 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.meta; -import java.lang.reflect.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; /** * Provides access to the metadata of a class typically provided in a class file. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java index 7bc325087af..c2df8929fbe 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java @@ -22,9 +22,17 @@ */ package jdk.vm.ci.meta; -import java.io.*; -import java.lang.reflect.*; -import java.util.*; +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; /** * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.meta} and its clients. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java index e4de0de87c8..8397fef5f08 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import java.lang.invoke.*; +import java.lang.invoke.MethodHandle; /** * Interface to access the internals of the {@link MethodHandle} implementation of the VM. An diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java index f6c20bba1a4..2f28c7e31f3 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java @@ -22,9 +22,20 @@ */ package jdk.vm.ci.meta; -import static java.lang.reflect.Modifier.*; +import static java.lang.reflect.Modifier.ABSTRACT; +import static java.lang.reflect.Modifier.FINAL; +import static java.lang.reflect.Modifier.INTERFACE; +import static java.lang.reflect.Modifier.NATIVE; +import static java.lang.reflect.Modifier.PRIVATE; +import static java.lang.reflect.Modifier.PROTECTED; +import static java.lang.reflect.Modifier.PUBLIC; +import static java.lang.reflect.Modifier.STATIC; +import static java.lang.reflect.Modifier.STRICT; +import static java.lang.reflect.Modifier.SYNCHRONIZED; +import static java.lang.reflect.Modifier.TRANSIENT; +import static java.lang.reflect.Modifier.VOLATILE; -import java.lang.reflect.*; +import java.lang.reflect.Modifier; /** * A Java element (i.e., a class, interface, field or method) that is described by a set of Java diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java index e1deacac143..6947c9aefea 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java @@ -29,8 +29,6 @@ public interface PlatformKind { String name(); - JavaConstant getDefaultValue(); - public interface Key { } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java index bf599debc7e..135b667e90c 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import java.nio.*; +import java.nio.ByteBuffer; /** * Represents a primitive constant value, such as an integer or floating point number, within the diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaField.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaField.java index 7a695f083a5..b1eb007c065 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaField.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaField.java @@ -22,8 +22,8 @@ */ package jdk.vm.ci.meta; -import java.lang.annotation.*; -import java.lang.reflect.*; +import java.lang.annotation.Annotation; +import java.lang.reflect.Modifier; /** * Represents a reference to a resolved Java field. Fields, like methods and types, are resolved diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java index 9e516534d16..326a24bd29e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -22,10 +22,12 @@ */ package jdk.vm.ci.meta; -import java.lang.annotation.*; -import java.lang.invoke.*; -import java.lang.reflect.*; -import java.util.*; +import java.lang.annotation.Annotation; +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; /** * Represents a resolved Java method. Methods, like fields and types, are resolved through diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java index 1f2bdf3e329..d46a0fc3dce 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java @@ -22,10 +22,10 @@ */ package jdk.vm.ci.meta; -import java.lang.annotation.*; -import java.net.*; +import java.lang.annotation.Annotation; +import java.net.URL; -import jdk.vm.ci.meta.Assumptions.*; +import jdk.vm.ci.meta.Assumptions.AssumptionResult; /** * Represents a resolved Java type. Types include primitives, objects, {@code void}, and arrays diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SerializableConstant.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SerializableConstant.java index 3c63b25298d..05231627c5a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SerializableConstant.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SerializableConstant.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.meta; -import java.nio.*; +import java.nio.ByteBuffer; /** * Represents a compile-time constant that can be converted to a byte array. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java index 57ed095a363..4330e65715e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java @@ -22,47 +22,38 @@ */ package jdk.vm.ci.meta; -import java.util.*; -import java.util.concurrent.*; - /** - * Manages a list of unique deoptimization reasons. + * Manages unique deoptimization reasons. Reasons are embedded in compiled code and can be + * invalidated at run time. Subsequent compilations then should not speculate again on such + * invalidated reasons to avoid repeated deoptimization. * + * All methods of this interface are called by the compiler. There is no need for API to register + * failed speculations during deoptimization, since every VM has different needs there. */ -public abstract class SpeculationLog { - private volatile Object lastFailed; - private volatile Collection speculations; - private Set failedSpeculations; +public interface SpeculationLog { - public synchronized void collectFailedSpeculations() { - if (lastFailed != null) { - if (failedSpeculations == null) { - failedSpeculations = new HashSet<>(2); - } - failedSpeculations.add(lastFailed); - lastFailed = null; - speculations = null; - } + /** + * Marker interface for speculation objects that can be added to the speculation log. + */ + public interface SpeculationReason { } - public boolean maySpeculate(Object reason) { - if (failedSpeculations != null && failedSpeculations.contains(reason)) { - return false; - } - return true; - } + /** + * Must be called before compilation, i.e., before a compiler calls {@link #maySpeculate}. + */ + void collectFailedSpeculations(); - protected void addSpeculation(Object reason) { - assert maySpeculate(reason); - if (speculations == null) { - synchronized (this) { - if (speculations == null) { - speculations = new ConcurrentLinkedQueue<>(); - } - } - } - speculations.add(reason); - } + /** + * If this method returns true, the compiler is allowed to {@link #speculate} with the given + * reason. + */ + boolean maySpeculate(SpeculationReason reason); - public abstract JavaConstant speculate(Object reason); + /** + * Registers a speculation that was performed by the compiler. + * + * @return A compiler constant encapsulating the provided reason. It is usually passed as an + * argument to the deoptimization function. + */ + JavaConstant speculate(SpeculationReason reason); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options.processor/src/jdk/vm/ci/options/processor/OptionProcessor.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options.processor/src/jdk/vm/ci/options/processor/OptionProcessor.java index 28153496314..95422c24135 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options.processor/src/jdk/vm/ci/options/processor/OptionProcessor.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options.processor/src/jdk/vm/ci/options/processor/OptionProcessor.java @@ -22,19 +22,40 @@ */ package jdk.vm.ci.options.processor; -import java.io.*; -import java.util.*; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; -import javax.annotation.processing.*; -import javax.lang.model.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Filer; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.Name; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; import javax.tools.Diagnostic.Kind; +import javax.tools.JavaFileObject; -import jdk.vm.ci.options.*; - -import javax.tools.*; +import jdk.vm.ci.options.Option; +import jdk.vm.ci.options.OptionDescriptor; +import jdk.vm.ci.options.OptionDescriptors; +import jdk.vm.ci.options.OptionValue; /** * Processes static fields annotated with {@link Option}. An {@link OptionDescriptors} @@ -105,11 +126,11 @@ public class OptionProcessor extends AbstractProcessor { DeclaredType declaredOptionValueType = declaredFieldType; while (!types.isSameType(types.erasure(declaredOptionValueType), types.erasure(optionValueType))) { List directSupertypes = types.directSupertypes(declaredFieldType); - assert!directSupertypes.isEmpty(); + assert !directSupertypes.isEmpty(); declaredOptionValueType = (DeclaredType) directSupertypes.get(0); } - assert!declaredOptionValueType.getTypeArguments().isEmpty(); + assert !declaredOptionValueType.getTypeArguments().isEmpty(); String optionType = declaredOptionValueType.getTypeArguments().get(0).toString(); if (optionType.startsWith("java.lang.")) { optionType = optionType.substring("java.lang.".length()); @@ -194,8 +215,7 @@ public class OptionProcessor extends AbstractProcessor { if (info.options.size() == 1) { out.printf(" return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue); } else { - out.printf(" case \"" + name + "\": return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, - optionValue); + out.printf(" case \"" + name + "\": return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue); } } out.println(" }"); @@ -241,19 +261,6 @@ public class OptionProcessor extends AbstractProcessor { } out.println("}"); } - - try { - createOptionsFile(pkg, topDeclaringClass.toString(), originatingElements); - } catch (IOException e) { - processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType); - } - } - - private void createOptionsFile(String pkg, String relativeName, Element... originatingElements) throws IOException { - String filename = "META-INF/jvmci.options/" + pkg + "." + relativeName; - FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements); - PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); - writer.close(); } protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/DerivedOptionValue.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/DerivedOptionValue.java index 267692a1c07..e6149955c77 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/DerivedOptionValue.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/DerivedOptionValue.java @@ -22,10 +22,10 @@ */ package jdk.vm.ci.options; -import java.io.*; -import java.util.function.*; +import java.io.Serializable; +import java.util.function.Supplier; -import jdk.vm.ci.options.OptionValue.*; +import jdk.vm.ci.options.OptionValue.OverrideScope; /** * A cached value that needs to be recomputed when an option changes. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/JVMCIJarsOptionDescriptorsProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/JVMCIJarsOptionDescriptorsProvider.java deleted file mode 100644 index a3603a4323a..00000000000 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/JVMCIJarsOptionDescriptorsProvider.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2014, 2015, 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.vm.ci.options; - -import java.io.*; -import java.util.*; -import java.util.jar.*; -import java.util.zip.*; - -import jdk.vm.ci.options.OptionsParser.*; - -/** - * Access to the {@link OptionDescriptors} declared by - * {@code META-INF/services/jdk.vm.ci.options.OptionDescriptors} files in {@code - * /lib/jvmci/*.jar}. - */ -class JVMCIJarsOptionDescriptorsProvider implements OptionDescriptorsProvider { - - static final String OptionDescriptorsServiceFile = "META-INF/services/" + OptionDescriptors.class.getName(); - - private final Iterator jars; - private final List optionsDescriptorsList; - - JVMCIJarsOptionDescriptorsProvider() { - List jarsList = findJVMCIJars(); - this.jars = jarsList.iterator(); - this.optionsDescriptorsList = new ArrayList<>(jarsList.size() * 3); - } - - /** - * Finds the list of JVMCI jars. - */ - private static List findJVMCIJars() { - File javaHome = new File(System.getProperty("java.home")); - File lib = new File(javaHome, "lib"); - File jvmci = new File(lib, "jvmci"); - - List jarFiles = new ArrayList<>(); - if (jvmci.exists()) { - for (String fileName : jvmci.list()) { - if (fileName.endsWith(".jar")) { - File file = new File(jvmci, fileName); - if (file.isDirectory()) { - continue; - } - jarFiles.add(file); - } - } - } - return jarFiles; - } - - public OptionDescriptor get(String name) { - // Look up loaded option descriptors first - for (OptionDescriptors optionDescriptors : optionsDescriptorsList) { - OptionDescriptor desc = optionDescriptors.get(name); - if (desc != null) { - return desc; - } - } - while (jars.hasNext()) { - File path = jars.next(); - try (JarFile jar = new JarFile(path)) { - ZipEntry entry = jar.getEntry(OptionDescriptorsServiceFile); - if (entry != null) { - BufferedReader br = new BufferedReader(new InputStreamReader(jar.getInputStream(entry))); - String line = null; - OptionDescriptor desc = null; - while ((line = br.readLine()) != null) { - OptionDescriptors options; - try { - options = (OptionDescriptors) Class.forName(line).newInstance(); - optionsDescriptorsList.add(options); - if (desc == null) { - desc = options.get(name); - } - } catch (Exception e) { - throw new InternalError("Error instantiating class " + line + " read from " + path, e); - } - } - if (desc != null) { - return desc; - } - } - } catch (IOException e) { - throw new InternalError("Error reading " + path, e); - } - } - return null; - } -} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/NestedBooleanOptionValue.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/NestedBooleanOptionValue.java index ffbaf4d0bd6..804603814f1 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/NestedBooleanOptionValue.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/NestedBooleanOptionValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/Option.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/Option.java index 5a9f920a198..3e0537335d3 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/Option.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/Option.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.options; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Describes the attributes of an option whose {@link OptionValue value} is in a static field diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionValue.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionValue.java index 343edb1d113..6abcc91d936 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionValue.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionValue.java @@ -22,9 +22,15 @@ */ package jdk.vm.ci.options; -import java.io.*; -import java.util.*; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; /** * An option value. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsLoader.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsLoader.java index 62cb9c80831..a01a05d040e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsLoader.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsLoader.java @@ -22,7 +22,9 @@ */ package jdk.vm.ci.options; -import java.util.*; +import java.util.ServiceLoader; +import java.util.SortedMap; +import java.util.TreeMap; /** * Helper class used to load option descriptors. Only to be used in the slow-path. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java index 59893978ae0..0b8a6411181 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java @@ -22,21 +22,33 @@ */ package jdk.vm.ci.options; -import static jdk.vm.ci.inittimer.InitTimer.*; +import static jdk.vm.ci.inittimer.InitTimer.timer; -import java.io.*; -import java.util.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Formatter; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.SortedMap; -import jdk.vm.ci.inittimer.*; +import jdk.vm.ci.inittimer.InitTimer; /** * This class contains methods for parsing JVMCI options and matching them against a set of - * {@link OptionDescriptors}. The {@link OptionDescriptors} are loaded from JVMCI jars, either - * {@linkplain JVMCIJarsOptionDescriptorsProvider directly} or via a {@link ServiceLoader}. + * {@link OptionDescriptors}. The {@link OptionDescriptors} are loaded via a {@link ServiceLoader}. */ public class OptionsParser { private static final OptionValue PrintFlags = new OptionValue<>(false); + private static final OptionValue ShowFlags = new OptionValue<>(false); /** * A service for looking up {@link OptionDescriptor}s. @@ -54,7 +66,7 @@ public class OptionsParser { } /** - * Parses the options in {@code /lib/jvmci/options} if {@code parseOptionsFile == true} and + * Parses the options in {@code /lib/jvmci.options} if {@code parseOptionsFile == true} and * the file exists followed by the JVMCI options in {@code options} if {@code options != null}. * * Called from VM. This method has an object return type to allow it to be called with a VM @@ -62,87 +74,158 @@ public class OptionsParser { * * @param options JVMCI options as serialized (name, value) pairs * @param parseOptionsFile specifies whether to look for and parse - * {@code /lib/jvmci/options} + * {@code /lib/jvmci.options} */ @SuppressWarnings("try") public static Boolean parseOptionsFromVM(String[] options, boolean parseOptionsFile) { + try (InitTimer t = timer("ParseOptions")) { - JVMCIJarsOptionDescriptorsProvider odp = new JVMCIJarsOptionDescriptorsProvider(); if (parseOptionsFile) { File javaHome = new File(System.getProperty("java.home")); File lib = new File(javaHome, "lib"); - File jvmci = new File(lib, "jvmci"); - File jvmciOptions = new File(jvmci, "options"); + File jvmciOptions = new File(lib, "jvmci.options"); if (jvmciOptions.exists()) { try (BufferedReader br = new BufferedReader(new FileReader(jvmciOptions))) { String optionSetting = null; int lineNo = 1; + List optionSettings = new ArrayList<>(); while ((optionSetting = br.readLine()) != null) { if (!optionSetting.isEmpty() && optionSetting.charAt(0) != '#') { try { - parseOptionSetting(optionSetting, null, odp); + parseOptionSettingTo(optionSetting, optionSettings); } catch (Throwable e) { throw new InternalError("Error parsing " + jvmciOptions + ", line " + lineNo, e); } } lineNo++; } + try { + parseOptions(optionSettings.toArray(new String[optionSettings.size()]), null, null, null); + } catch (Throwable e) { + throw new InternalError("Error parsing an option from " + jvmciOptions, e); + } } catch (IOException e) { throw new InternalError("Error reading " + jvmciOptions, e); } } } - if (options != null) { - assert options.length % 2 == 0; - for (int i = 0; i < options.length / 2; i++) { - String name = options[i * 2]; - String value = options[i * 2 + 1]; - parseOption(OptionsLoader.options, name, value, null, odp); - } - } + parseOptions(options, null, null, null); } return Boolean.TRUE; } /** - * Parses a given option setting. + * Parses an ordered list of (name, value) pairs assigning values to JVMCI options. + * + * @param optionSettings JVMCI options as serialized (name, value) pairs + * @param setter the object to notify of the parsed option and value + * @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s + * @param options the options database to use if {@code odp == null}. If + * {@code options == null && odp == null}, {@link OptionsLoader#options} is used. + * @throws IllegalArgumentException if there's a problem parsing {@code option} + */ + public static void parseOptions(String[] optionSettings, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap options) { + if (optionSettings != null && optionSettings.length != 0) { + assert optionSettings.length % 2 == 0; + + moveHelpFlagsToTail(optionSettings); + + for (int i = 0; i < optionSettings.length / 2; i++) { + String name = optionSettings[i * 2]; + String value = optionSettings[i * 2 + 1]; + parseOption(name, value, setter, odp, options); + } + if (PrintFlags.getValue() || ShowFlags.getValue()) { + Set explicitlyAssigned = new HashSet<>(optionSettings.length / 2); + for (int i = 0; i < optionSettings.length / 2; i++) { + String name = optionSettings[i * 2]; + explicitlyAssigned.add(name); + } + printFlags(resolveOptions(options), "JVMCI", System.out, explicitlyAssigned); + if (PrintFlags.getValue()) { + System.exit(0); + } + } + } + } + + /** + * Moves all {@code PrintFlags} and {@code ShowFlags} option settings to the back of + * {@code optionSettings}. This allows the help message to show which options had their value + * explicitly set (even if to their default value). + */ + private static void moveHelpFlagsToTail(String[] optionSettings) { + List tail = null; + int insert = 0; + for (int i = 0; i < optionSettings.length / 2; i++) { + String name = optionSettings[i * 2]; + String value = optionSettings[i * 2 + 1]; + if (name.equals("ShowFlags") || name.equals("PrintFlags")) { + if (tail == null) { + tail = new ArrayList<>(4); + insert = i * 2; + } + tail.add(name); + tail.add(value); + } else if (tail != null) { + optionSettings[insert++] = name; + optionSettings[insert++] = value; + } + } + if (tail != null) { + assert tail.size() + insert == optionSettings.length; + String[] tailArr = tail.toArray(new String[tail.size()]); + System.arraycopy(tailArr, 0, optionSettings, insert, tailArr.length); + } + } + + /** + * Parses a given option setting string to a list of (name, value) pairs. * * @param optionSetting a string matching the pattern {@code =} - * @param setter the object to notify of the parsed option and value */ - public static void parseOptionSetting(String optionSetting, OptionConsumer setter, OptionDescriptorsProvider odp) { + public static void parseOptionSettingTo(String optionSetting, List dst) { int eqIndex = optionSetting.indexOf('='); if (eqIndex == -1) { throw new InternalError("Option setting has does not match the pattern =: " + optionSetting); } - String name = optionSetting.substring(0, eqIndex); - String value = optionSetting.substring(eqIndex + 1); - parseOption(OptionsLoader.options, name, value, setter, odp); + dst.add(optionSetting.substring(0, eqIndex)); + dst.add(optionSetting.substring(eqIndex + 1)); + } + + /** + * Resolves {@code options} to a non-null value. This ensures {@link OptionsLoader#options} is + * only loaded if necessary. + */ + private static SortedMap resolveOptions(SortedMap options) { + return options != null ? options : OptionsLoader.options; } /** * Parses a given option name and value. * - * @param options * @param name the option name * @param valueString the option value as a string * @param setter the object to notify of the parsed option and value - * @param odp - * + * @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s + * @param options the options database to use if {@code odp == null}. If + * {@code options == null && odp == null}, {@link OptionsLoader#options} is used. * @throws IllegalArgumentException if there's a problem parsing {@code option} */ - public static void parseOption(SortedMap options, String name, String valueString, OptionConsumer setter, OptionDescriptorsProvider odp) { - OptionDescriptor desc = options.get(name); - if (desc == null && odp != null) { - desc = odp.get(name); - } - if (desc == null && name.equals("PrintFlags")) { - desc = OptionDescriptor.create("PrintFlags", Boolean.class, "Prints all JVMCI flags and exits", OptionsParser.class, "PrintFlags", PrintFlags); + private static void parseOption(String name, String valueString, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap options) { + + OptionDescriptor desc = odp != null ? odp.get(name) : resolveOptions(options).get(name); + if (desc == null) { + if (name.equals("PrintFlags")) { + desc = OptionDescriptor.create("PrintFlags", Boolean.class, "Prints all JVMCI flags and exits", OptionsParser.class, "PrintFlags", PrintFlags); + } else if (name.equals("ShowFlags")) { + desc = OptionDescriptor.create("ShowFlags", Boolean.class, "Prints all JVMCI flags and continues", OptionsParser.class, "ShowFlags", ShowFlags); + } } if (desc == null) { - List matches = fuzzyMatch(options, name); + List matches = fuzzyMatch(resolveOptions(options), name); Formatter msg = new Formatter(); msg.format("Could not find option %s", name); if (!matches.isEmpty()) { @@ -182,11 +265,6 @@ public class OptionsParser { } else { setter.set(desc, value); } - - if (PrintFlags.getValue()) { - printFlags(options, "JVMCI", System.out); - System.exit(0); - } } private static long parseLong(String v) { @@ -252,16 +330,18 @@ public class OptionsParser { return lines; } - public static void printFlags(SortedMap sortedOptions, String prefix, PrintStream out) { + private static void printFlags(SortedMap sortedOptions, String prefix, PrintStream out, Set explicitlyAssigned) { out.println("[List of " + prefix + " options]"); for (Map.Entry e : sortedOptions.entrySet()) { e.getKey(); OptionDescriptor desc = e.getValue(); Object value = desc.getOptionValue().getValue(); List helpLines = wrap(desc.getHelp(), 70); - out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0))); + String name = e.getKey(); + String assign = explicitlyAssigned.contains(name) ? ":=" : " ="; + out.printf("%9s %-40s %s %-14s %s%n", desc.getType().getSimpleName(), name, assign, value, helpLines.get(0)); for (int i = 1; i < helpLines.size(); i++) { - out.println(String.format("%67s %s", " ", helpLines.get(i))); + out.printf("%67s %s%n", " ", helpLines.get(i)); } } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java index 886702a5485..3b4f073dc87 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.runtime; -import java.util.*; +import java.util.Formatter; public class JVMCI { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIBackend.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIBackend.java index 98b02cf4cca..28b296e095b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIBackend.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIBackend.java @@ -22,8 +22,11 @@ */ package jdk.vm.ci.runtime; -import jdk.vm.ci.code.*; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.CodeCacheProvider; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.code.stack.StackIntrospection; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; /** * A JVMCI backend encapsulates the capabilities needed by a Java based compiler for compiling and @@ -35,11 +38,13 @@ public class JVMCIBackend { private final MetaAccessProvider metaAccess; private final CodeCacheProvider codeCache; private final ConstantReflectionProvider constantReflection; + private final StackIntrospection stackIntrospection; - public JVMCIBackend(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection) { + public JVMCIBackend(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, StackIntrospection stackIntrospection) { this.metaAccess = metaAccess; this.codeCache = codeCache; this.constantReflection = constantReflection; + this.stackIntrospection = stackIntrospection; } public MetaAccessProvider getMetaAccess() { @@ -57,4 +62,8 @@ public class JVMCIBackend { public TargetDescription getTarget() { return codeCache.getTarget(); } + + public StackIntrospection getStackIntrospection() { + return stackIntrospection; + } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompiler.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompiler.java new file mode 100644 index 00000000000..72a1b53b8f9 --- /dev/null +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompiler.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015, 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.vm.ci.runtime; + +import jdk.vm.ci.code.CompilationRequest; + +public interface JVMCICompiler { + int INVOCATION_ENTRY_BCI = -1; + + /** + * Services a compilation request. This object should compile the method to machine code and + * install it in the code cache if the compilation is successful. + */ + void compileMethod(CompilationRequest request); +} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/CompilerFactory.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompilerFactory.java similarity index 61% rename from hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/CompilerFactory.java rename to hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompilerFactory.java index 98e08dc0e82..7bb1f592224 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/CompilerFactory.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompilerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -20,15 +20,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.vm.ci.compiler; - -import jdk.vm.ci.code.*; -import jdk.vm.ci.runtime.*; +package jdk.vm.ci.runtime; /** * Factory for a JVMCI compiler. */ -public interface CompilerFactory { +public interface JVMCICompilerFactory { /** * Get the name of this compiler. The compiler will be selected when the jvmci.compiler system @@ -37,13 +34,20 @@ public interface CompilerFactory { String getCompilerName(); /** - * Initialize an {@link Architecture}. The compiler has the opportunity to extend the - * {@link Architecture} description with a custom subclass. + * Create a new instance of the {@link JVMCICompiler}. */ - Architecture initializeArchitecture(Architecture arch); + JVMCICompiler createCompiler(JVMCIRuntime runtime); /** - * Create a new instance of the {@link Compiler}. + * In a tiered system it might be advantageous for startup to keep the JVMCI compiler from + * compiling itself so provide a hook to request that certain packages are compiled only by an + * optimizing first tier. The prefixes should class or package names using / as the separator, + * i.e. jdk/vm/ci for instance. + * + * @return 0 or more Strings identifying packages that should by compiled by the first tier + * only. */ - Compiler createCompiler(JVMCIRuntime runtime); + default String[] getTrivialPrefixes() { + return null; + } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIRuntime.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIRuntime.java index 960a1d62e53..b705417e941 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIRuntime.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIRuntime.java @@ -22,13 +22,18 @@ */ package jdk.vm.ci.runtime; -import jdk.vm.ci.code.*; +import jdk.vm.ci.code.Architecture; /** * Interface for accessing the {@link JVMCI} APIs supported by the runtime. */ public interface JVMCIRuntime { + /** + * Gets the default system compiler. + */ + JVMCICompiler getCompiler(); + /** * Gets the host JVMCI backend. */ diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service.processor/src/jdk/vm/ci/service/processor/ServiceProviderProcessor.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service.processor/src/jdk/vm/ci/service/processor/ServiceProviderProcessor.java index 4b027c3c0bb..d8aea467257 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service.processor/src/jdk/vm/ci/service/processor/ServiceProviderProcessor.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service.processor/src/jdk/vm/ci/service/processor/ServiceProviderProcessor.java @@ -22,18 +22,25 @@ */ package jdk.vm.ci.service.processor; -import java.io.*; -import java.util.*; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.HashSet; +import java.util.Set; -import javax.annotation.processing.*; -import javax.lang.model.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.MirroredTypeException; +import javax.lang.model.type.TypeMirror; import javax.tools.Diagnostic.Kind; +import javax.tools.FileObject; +import javax.tools.StandardLocation; -import jdk.vm.ci.service.*; - -import javax.tools.*; +import jdk.vm.ci.service.ServiceProvider; @SupportedAnnotationTypes("jdk.vm.ci.service.ServiceProvider") public class ServiceProviderProcessor extends AbstractProcessor { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/.checkstyle_checks.xml b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/.checkstyle_checks.xml index 4ae5b12b06a..003d8f7dcb5 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/.checkstyle_checks.xml +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/.checkstyle_checks.xml @@ -32,6 +32,10 @@ + + + + diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/ServiceProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/ServiceProvider.java index 0263d5afd59..4d8a7f9692b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/ServiceProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/ServiceProvider.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.service; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Annotates a service provider than can be loaded via {@linkplain Services#load(Class)} or diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/Services.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/Services.java index 6b574badf24..9a6263a9b99 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/Services.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/Services.java @@ -22,7 +22,10 @@ */ package jdk.vm.ci.service; -import java.util.*; +import java.util.Formatter; +import java.util.Iterator; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; /** * A mechanism for accessing service providers via JVMCI. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java index a68c68e6adb..7f99e331e1b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java @@ -22,14 +22,18 @@ */ package jdk.vm.ci.sparc; -import static java.nio.ByteOrder.*; -import static jdk.vm.ci.code.MemoryBarriers.*; +import static java.nio.ByteOrder.BIG_ENDIAN; +import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD; +import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; +import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; -import java.util.*; +import java.util.Set; -import jdk.vm.ci.code.*; +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register.RegisterCategory; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.PlatformKind; /** * Represents the SPARC architecture. @@ -37,95 +41,50 @@ import jdk.vm.ci.meta.*; public class SPARC extends Architecture { public static final RegisterCategory CPU = new RegisterCategory("CPU"); + public static final RegisterCategory FPUs = new RegisterCategory("FPUs"); + public static final RegisterCategory FPUd = new RegisterCategory("FPUd"); + public static final RegisterCategory FPUq = new RegisterCategory("FPUq"); // General purpose registers - public static final Register r0 = new Register(0, 0, "g0", CPU); - public static final Register r1 = new Register(1, 1, "g1", CPU); - public static final Register r2 = new Register(2, 2, "g2", CPU); - public static final Register r3 = new Register(3, 3, "g3", CPU); - public static final Register r4 = new Register(4, 4, "g4", CPU); - public static final Register r5 = new Register(5, 5, "g5", CPU); - public static final Register r6 = new Register(6, 6, "g6", CPU); - public static final Register r7 = new Register(7, 7, "g7", CPU); + public static final Register g0 = new Register(0, 0, "g0", CPU); + public static final Register g1 = new Register(1, 1, "g1", CPU); + public static final Register g2 = new Register(2, 2, "g2", CPU); + public static final Register g3 = new Register(3, 3, "g3", CPU); + public static final Register g4 = new Register(4, 4, "g4", CPU); + public static final Register g5 = new Register(5, 5, "g5", CPU); + public static final Register g6 = new Register(6, 6, "g6", CPU); + public static final Register g7 = new Register(7, 7, "g7", CPU); - public static final Register r8 = new Register(8, 8, "o0", CPU); - public static final Register r9 = new Register(9, 9, "o1", CPU); - public static final Register r10 = new Register(10, 10, "o2", CPU); - public static final Register r11 = new Register(11, 11, "o3", CPU); - public static final Register r12 = new Register(12, 12, "o4", CPU); - public static final Register r13 = new Register(13, 13, "o5", CPU); - public static final Register r14 = new Register(14, 14, "o6", CPU); - public static final Register r15 = new Register(15, 15, "o7", CPU); + public static final Register o0 = new Register(8, 8, "o0", CPU); + public static final Register o1 = new Register(9, 9, "o1", CPU); + public static final Register o2 = new Register(10, 10, "o2", CPU); + public static final Register o3 = new Register(11, 11, "o3", CPU); + public static final Register o4 = new Register(12, 12, "o4", CPU); + public static final Register o5 = new Register(13, 13, "o5", CPU); + public static final Register o6 = new Register(14, 14, "o6", CPU); + public static final Register o7 = new Register(15, 15, "o7", CPU); - public static final Register r16 = new Register(16, 16, "l0", CPU); - public static final Register r17 = new Register(17, 17, "l1", CPU); - public static final Register r18 = new Register(18, 18, "l2", CPU); - public static final Register r19 = new Register(19, 19, "l3", CPU); - public static final Register r20 = new Register(20, 20, "l4", CPU); - public static final Register r21 = new Register(21, 21, "l5", CPU); - public static final Register r22 = new Register(22, 22, "l6", CPU); - public static final Register r23 = new Register(23, 23, "l7", CPU); + public static final Register l0 = new Register(16, 16, "l0", CPU); + public static final Register l1 = new Register(17, 17, "l1", CPU); + public static final Register l2 = new Register(18, 18, "l2", CPU); + public static final Register l3 = new Register(19, 19, "l3", CPU); + public static final Register l4 = new Register(20, 20, "l4", CPU); + public static final Register l5 = new Register(21, 21, "l5", CPU); + public static final Register l6 = new Register(22, 22, "l6", CPU); + public static final Register l7 = new Register(23, 23, "l7", CPU); - public static final Register r24 = new Register(24, 24, "i0", CPU); - public static final Register r25 = new Register(25, 25, "i1", CPU); - public static final Register r26 = new Register(26, 26, "i2", CPU); - public static final Register r27 = new Register(27, 27, "i3", CPU); - public static final Register r28 = new Register(28, 28, "i4", CPU); - public static final Register r29 = new Register(29, 29, "i5", CPU); - public static final Register r30 = new Register(30, 30, "i6", CPU); - public static final Register r31 = new Register(31, 31, "i7", CPU); - - public static final Register g0 = r0; - public static final Register g1 = r1; - public static final Register g2 = r2; - public static final Register g3 = r3; - public static final Register g4 = r4; - public static final Register g5 = r5; - public static final Register g6 = r6; - public static final Register g7 = r7; - - public static final Register o0 = r8; - public static final Register o1 = r9; - public static final Register o2 = r10; - public static final Register o3 = r11; - public static final Register o4 = r12; - public static final Register o5 = r13; - public static final Register o6 = r14; - public static final Register o7 = r15; - - public static final Register l0 = r16; - public static final Register l1 = r17; - public static final Register l2 = r18; - public static final Register l3 = r19; - public static final Register l4 = r20; - public static final Register l5 = r21; - public static final Register l6 = r22; - public static final Register l7 = r23; - - public static final Register i0 = r24; - public static final Register i1 = r25; - public static final Register i2 = r26; - public static final Register i3 = r27; - public static final Register i4 = r28; - public static final Register i5 = r29; - public static final Register i6 = r30; - public static final Register i7 = r31; + public static final Register i0 = new Register(24, 24, "i0", CPU); + public static final Register i1 = new Register(25, 25, "i1", CPU); + public static final Register i2 = new Register(26, 26, "i2", CPU); + public static final Register i3 = new Register(27, 27, "i3", CPU); + public static final Register i4 = new Register(28, 28, "i4", CPU); + public static final Register i5 = new Register(29, 29, "i5", CPU); + public static final Register i6 = new Register(30, 30, "i6", CPU); + public static final Register i7 = new Register(31, 31, "i7", CPU); public static final Register sp = o6; public static final Register fp = i6; - // @formatter:off - public static final Register[] cpuRegisters = { - r0, r1, r2, r3, r4, r5, r6, r7, - r8, r9, r10, r11, r12, r13, r14, r15, - r16, r17, r18, r19, r20, r21, r22, r23, - r24, r25, r26, r27, r28, r29, r30, r31 - }; - // @formatter:on - - public static final RegisterCategory FPUs = new RegisterCategory("FPUs", cpuRegisters.length); - public static final RegisterCategory FPUd = new RegisterCategory("FPUd", cpuRegisters.length + 32); - // Floating point registers public static final Register f0 = new Register(32, 0, "f0", FPUs); public static final Register f1 = new Register(33, 1, "f1", FPUs); @@ -163,67 +122,111 @@ public class SPARC extends Architecture { public static final Register f30 = new Register(62, 30, "f30", FPUs); public static final Register f31 = new Register(63, 31, "f31", FPUs); - public static final Register d0 = new Register(32, getDoubleEncoding(0), "d0", FPUs); - public static final Register d2 = new Register(34, getDoubleEncoding(2), "d2", FPUs); - public static final Register d4 = new Register(36, getDoubleEncoding(4), "d4", FPUs); - public static final Register d6 = new Register(38, getDoubleEncoding(6), "d6", FPUs); - public static final Register d8 = new Register(40, getDoubleEncoding(8), "d8", FPUs); - public static final Register d10 = new Register(42, getDoubleEncoding(10), "d10", FPUs); - public static final Register d12 = new Register(44, getDoubleEncoding(12), "d12", FPUs); - public static final Register d14 = new Register(46, getDoubleEncoding(14), "d14", FPUs); + // Double precision registers + public static final Register d0 = new Register(64, getDoubleEncoding(0), "d0", FPUd); + public static final Register d2 = new Register(65, getDoubleEncoding(2), "d2", FPUd); + public static final Register d4 = new Register(66, getDoubleEncoding(4), "d4", FPUd); + public static final Register d6 = new Register(67, getDoubleEncoding(6), "d6", FPUd); + public static final Register d8 = new Register(68, getDoubleEncoding(8), "d8", FPUd); + public static final Register d10 = new Register(69, getDoubleEncoding(10), "d10", FPUd); + public static final Register d12 = new Register(70, getDoubleEncoding(12), "d12", FPUd); + public static final Register d14 = new Register(71, getDoubleEncoding(14), "d14", FPUd); - public static final Register d16 = new Register(48, getDoubleEncoding(16), "d16", FPUs); - public static final Register d18 = new Register(50, getDoubleEncoding(18), "d18", FPUs); - public static final Register d20 = new Register(52, getDoubleEncoding(20), "d20", FPUs); - public static final Register d22 = new Register(54, getDoubleEncoding(22), "d22", FPUs); - public static final Register d24 = new Register(56, getDoubleEncoding(24), "d24", FPUs); - public static final Register d26 = new Register(58, getDoubleEncoding(26), "d26", FPUs); - public static final Register d28 = new Register(60, getDoubleEncoding(28), "d28", FPUs); - public static final Register d30 = new Register(62, getDoubleEncoding(28), "d28", FPUs); + public static final Register d16 = new Register(72, getDoubleEncoding(16), "d16", FPUd); + public static final Register d18 = new Register(73, getDoubleEncoding(18), "d18", FPUd); + public static final Register d20 = new Register(74, getDoubleEncoding(20), "d20", FPUd); + public static final Register d22 = new Register(75, getDoubleEncoding(22), "d22", FPUd); + public static final Register d24 = new Register(76, getDoubleEncoding(24), "d24", FPUd); + public static final Register d26 = new Register(77, getDoubleEncoding(26), "d26", FPUd); + public static final Register d28 = new Register(78, getDoubleEncoding(28), "d28", FPUd); + public static final Register d30 = new Register(79, getDoubleEncoding(28), "d28", FPUd); - public static final Register d32 = new Register(64, getDoubleEncoding(32), "d32", FPUd); - public static final Register d34 = new Register(65, getDoubleEncoding(34), "d34", FPUd); - public static final Register d36 = new Register(66, getDoubleEncoding(36), "d36", FPUd); - public static final Register d38 = new Register(67, getDoubleEncoding(38), "d38", FPUd); - public static final Register d40 = new Register(68, getDoubleEncoding(40), "d40", FPUd); - public static final Register d42 = new Register(69, getDoubleEncoding(42), "d42", FPUd); - public static final Register d44 = new Register(70, getDoubleEncoding(44), "d44", FPUd); - public static final Register d46 = new Register(71, getDoubleEncoding(46), "d46", FPUd); + public static final Register d32 = new Register(80, getDoubleEncoding(32), "d32", FPUd); + public static final Register d34 = new Register(81, getDoubleEncoding(34), "d34", FPUd); + public static final Register d36 = new Register(82, getDoubleEncoding(36), "d36", FPUd); + public static final Register d38 = new Register(83, getDoubleEncoding(38), "d38", FPUd); + public static final Register d40 = new Register(84, getDoubleEncoding(40), "d40", FPUd); + public static final Register d42 = new Register(85, getDoubleEncoding(42), "d42", FPUd); + public static final Register d44 = new Register(86, getDoubleEncoding(44), "d44", FPUd); + public static final Register d46 = new Register(87, getDoubleEncoding(46), "d46", FPUd); - public static final Register d48 = new Register(72, getDoubleEncoding(48), "d48", FPUd); - public static final Register d50 = new Register(73, getDoubleEncoding(50), "d50", FPUd); - public static final Register d52 = new Register(74, getDoubleEncoding(52), "d52", FPUd); - public static final Register d54 = new Register(75, getDoubleEncoding(54), "d54", FPUd); - public static final Register d56 = new Register(76, getDoubleEncoding(56), "d56", FPUd); - public static final Register d58 = new Register(77, getDoubleEncoding(58), "d58", FPUd); - public static final Register d60 = new Register(78, getDoubleEncoding(60), "d60", FPUd); - public static final Register d62 = new Register(79, getDoubleEncoding(62), "d62", FPUd); + public static final Register d48 = new Register(88, getDoubleEncoding(48), "d48", FPUd); + public static final Register d50 = new Register(89, getDoubleEncoding(50), "d50", FPUd); + public static final Register d52 = new Register(90, getDoubleEncoding(52), "d52", FPUd); + public static final Register d54 = new Register(91, getDoubleEncoding(54), "d54", FPUd); + public static final Register d56 = new Register(92, getDoubleEncoding(56), "d56", FPUd); + public static final Register d58 = new Register(93, getDoubleEncoding(58), "d58", FPUd); + public static final Register d60 = new Register(94, getDoubleEncoding(60), "d60", FPUd); + public static final Register d62 = new Register(95, getDoubleEncoding(62), "d62", FPUd); + + // Quad precision registers + public static final Register q0 = new Register(96, getQuadncoding(0), "q0", FPUq); + public static final Register q4 = new Register(97, getQuadncoding(4), "q4", FPUq); + public static final Register q8 = new Register(98, getQuadncoding(8), "q8", FPUq); + public static final Register q12 = new Register(99, getQuadncoding(12), "q12", FPUq); + public static final Register q16 = new Register(100, getQuadncoding(16), "q16", FPUq); + public static final Register q20 = new Register(101, getQuadncoding(20), "q20", FPUq); + public static final Register q24 = new Register(102, getQuadncoding(24), "q24", FPUq); + public static final Register q28 = new Register(103, getQuadncoding(28), "q28", FPUq); + + public static final Register q32 = new Register(104, getQuadncoding(32), "q32", FPUq); + public static final Register q36 = new Register(105, getQuadncoding(36), "q36", FPUq); + public static final Register q40 = new Register(106, getQuadncoding(40), "q40", FPUq); + public static final Register q44 = new Register(107, getQuadncoding(44), "q44", FPUq); + public static final Register q48 = new Register(108, getQuadncoding(48), "q48", FPUq); + public static final Register q52 = new Register(109, getQuadncoding(52), "q52", FPUq); + public static final Register q56 = new Register(110, getQuadncoding(56), "q56", FPUq); + public static final Register q60 = new Register(111, getQuadncoding(60), "q60", FPUq); // @formatter:off - public static final Register[] fpuRegisters = { + public static final Register[] cpuRegisters = { + g0, g1, g2, g3, g4, g5, g6, g7, + o0, o1, o2, o3, o4, o5, o6, o7, + l0, l1, l2, l3, l4, l5, l6, l7, + i0, i1, i2, i3, i4, i5, i6, i7 + }; + + public static final Register[] fpusRegisters = { f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, - f24, f25, f26, f27, f28, f29, f30, f31, + f24, f25, f26, f27, f28, f29, f30, f31 + }; + + public static final Register[] fpudRegisters = { + d0, d2, d4, d6, d8, d10, d12, d14, + d16, d18, d20, d22, d24, d26, d28, d30, d32, d34, d36, d38, d40, d42, d44, d46, d48, d50, d52, d54, d56, d58, d60, d62 }; - // @formatter:on - // @formatter:off + public static final Register[] fpuqRegisters = { + q0, q4, q8, q12, + q16, q20, q24, q28, + q32, q36, q40, q44, + q48, q52, q56, q60, + }; + public static final Register[] allRegisters = { - // CPU - r0, r1, r2, r3, r4, r5, r6, r7, - r8, r9, r10, r11, r12, r13, r14, r15, - r16, r17, r18, r19, r20, r21, r22, r23, - r24, r25, r26, r27, r28, r29, r30, r31, - // FPU + g0, g1, g2, g3, g4, g5, g6, g7, + o0, o1, o2, o3, o4, o5, o6, o7, + l0, l1, l2, l3, l4, l5, l6, l7, + i0, i1, i2, i3, i4, i5, i6, i7, + f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30, f31, + + d0, d2, d4, d6, d8, d10, d12, d14, + d16, d18, d20, d22, d24, d26, d28, d30, d32, d34, d36, d38, d40, d42, d44, d46, - d48, d50, d52, d54, d56, d58, d60, d62 + d48, d50, d52, d54, d56, d58, d60, d62, + + q0, q4, q8, q12, + q16, q20, q24, q28, + q32, q36, q40, q44, + q48, q52, q56, q60, }; // @formatter:on @@ -231,18 +234,6 @@ public class SPARC extends Architecture { * Stack bias for stack and frame pointer loads. */ public static final int STACK_BIAS = 0x7ff; - /** - * In fact there are 64 single floating point registers, 32 of them could be accessed. TODO: - * Improve handling of these float registers - */ - public static final int FLOAT_REGISTER_COUNT = 64; - - /** - * Alignment for valid memory access. - */ - public static final int MEMORY_ACCESS_ALIGN = 4; - - public static final int INSTRUCTION_SIZE = 4; /** * Size to keep free for flushing the register-window to stack. @@ -252,90 +243,87 @@ public class SPARC extends Architecture { public final Set features; public SPARC(Set features) { - super("SPARC", JavaKind.Long, BIG_ENDIAN, false, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, r31.encoding + FLOAT_REGISTER_COUNT + 1, 8); + super("SPARC", SPARCKind.XWORD, BIG_ENDIAN, false, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8); this.features = features; } @Override - public boolean canStoreValue(RegisterCategory category, PlatformKind lirKind) { - if (!(lirKind instanceof JavaKind)) { - return false; - } + public Register[] getAvailableValueRegisters() { + return allRegisters; + } - JavaKind kind = (JavaKind) lirKind; - if (category.equals(CPU)) { - switch (kind) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - case Long: - return true; - } - } else if (category.equals(FPUs) && kind.equals(JavaKind.Float)) { - return true; - } else if (category.equals(FPUd) && kind.equals(JavaKind.Double)) { - return true; + @Override + public boolean canStoreValue(RegisterCategory category, PlatformKind kind) { + SPARCKind sparcKind = (SPARCKind) kind; + switch (sparcKind) { + case BYTE: + case HWORD: + case WORD: + case XWORD: + return CPU.equals(category); + case SINGLE: + case V32_BYTE: + case V32_HWORD: + return FPUs.equals(category); + case DOUBLE: + case V64_BYTE: + case V64_HWORD: + case V64_WORD: + case V64_SINGLE: + return FPUd.equals(category); + case QUAD: + return FPUq.equals(category); + default: + return false; } - return false; } @Override public PlatformKind getLargestStorableKind(RegisterCategory category) { if (category.equals(CPU)) { - return JavaKind.Long; + return SPARCKind.XWORD; } else if (category.equals(FPUd)) { - return JavaKind.Double; + return SPARCKind.DOUBLE; } else if (category.equals(FPUs)) { - return JavaKind.Float; + return SPARCKind.SINGLE; + } else if (category.equals(FPUq)) { + return SPARCKind.QUAD; } else { - return JavaKind.Illegal; + throw new IllegalArgumentException("Unknown register category: " + category); } } @Override public PlatformKind getPlatformKind(JavaKind javaKind) { - if (javaKind.isObject()) { - return JavaKind.Long; - } else { - return javaKind; + switch (javaKind) { + case Boolean: + case Byte: + return SPARCKind.BYTE; + case Short: + case Char: + return SPARCKind.HWORD; + case Int: + return SPARCKind.WORD; + case Long: + case Object: + return SPARCKind.XWORD; + case Float: + return SPARCKind.SINGLE; + case Double: + return SPARCKind.DOUBLE; + default: + throw new IllegalArgumentException("Unknown JavaKind: " + javaKind); } } - public static int spillSlotSize(TargetDescription td, PlatformKind kind) { - return Math.max(td.getSizeInBytes(kind), MEMORY_ACCESS_ALIGN); - } - - public static int getDoubleEncoding(int reg) { + private static int getDoubleEncoding(int reg) { assert reg < 64 && ((reg & 1) == 0); - // ignore v8 assertion for now return (reg & 0x1e) | ((reg & 0x20) >> 5); } - public static boolean isCPURegister(Register r) { - return r.getRegisterCategory().equals(CPU); - } - - public static boolean isCPURegister(Register... regs) { - for (Register reg : regs) { - if (!isCPURegister(reg)) { - return false; - } - } - return true; - } - - public static boolean isGlobalRegister(Register r) { - return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number; - } - - public static boolean isSingleFloatRegister(Register r) { - return r.name.startsWith("f"); - } - - public static boolean isDoubleFloatRegister(Register r) { - return r.name.startsWith("d"); + private static int getQuadncoding(int reg) { + assert reg < 64 && ((reg & 1) == 0); + return (reg & 0x1c) | ((reg & 0x20) >> 5); } public Set getFeatures() { @@ -351,6 +339,24 @@ public class SPARC extends Architecture { VIS2, VIS3, CBCOND, - BLOCK_ZEROING + V8, + HARDWARE_MUL32, + HARDWARE_DIV32, + HARDWARE_FSMULD, + HARDWARE_POPC, + V9, + SUN4V, + BLK_INIT_INSTRUCTIONS, + FMAF, + FMAU, + SPARC64_FAMILY, + M_FAMILY, + T_FAMILY, + T1_MODEL, + SPARC5, + AES, + SHA1, + SHA256, + SHA512 } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARCKind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARCKind.java new file mode 100644 index 00000000000..0e2fcae46b5 --- /dev/null +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARCKind.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015, 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.vm.ci.sparc; + +import jdk.vm.ci.meta.PlatformKind; + +public enum SPARCKind implements PlatformKind { + BYTE(1), + HWORD(2), + WORD(4), + XWORD(8), + SINGLE(4), + DOUBLE(8), + QUAD(16), + + V32_BYTE(4, BYTE), + V32_HWORD(4, HWORD), + + V64_BYTE(8, BYTE), + V64_HWORD(8, HWORD), + V64_WORD(8, WORD), + V64_SINGLE(8, SINGLE); + + private final int size; + private final int vectorLength; + + private final SPARCKind scalar; + private final EnumKey key = new EnumKey<>(this); + + private SPARCKind(int size) { + this.size = size; + this.scalar = this; + this.vectorLength = 1; + } + + private SPARCKind(int size, SPARCKind scalar) { + this.size = size; + this.scalar = scalar; + + assert size % scalar.size == 0; + this.vectorLength = size / scalar.size; + } + + public SPARCKind getScalar() { + return scalar; + } + + public int getSizeInBytes() { + return size; + } + + public int getSizeInBits() { + return getSizeInBytes() * 8; + } + + public int getVectorLength() { + return vectorLength; + } + + public Key getKey() { + return key; + } + + public boolean isInteger() { + switch (this) { + case BYTE: + case HWORD: + case WORD: + case XWORD: + return true; + default: + return false; + } + } + + public boolean isFloat() { + return !isInteger(); + } + + public char getTypeChar() { + switch (this) { + case BYTE: + return 'b'; + case HWORD: + return 'h'; + case WORD: + return 'w'; + case XWORD: + return 'd'; + case SINGLE: + return 'S'; + case DOUBLE: + case V64_BYTE: + case V64_HWORD: + case V64_WORD: + return 'D'; + default: + return '-'; + } + } +} diff --git a/hotspot/src/os/aix/vm/jvm_aix.cpp b/hotspot/src/os/aix/vm/jvm_aix.cpp index da41a6d6bab..4e95697a241 100644 --- a/hotspot/src/os/aix/vm/jvm_aix.cpp +++ b/hotspot/src/os/aix/vm/jvm_aix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2013 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -48,7 +48,6 @@ JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler)) : handler; switch (sig) { /* The following are already used by the VM. */ - case INTERRUPT_SIGNAL: case SIGFPE: case SIGILL: case SIGSEGV: diff --git a/hotspot/src/os/aix/vm/jvm_aix.h b/hotspot/src/os/aix/vm/jvm_aix.h index 6e70e7adce5..cdea3126bde 100644 --- a/hotspot/src/os/aix/vm/jvm_aix.h +++ b/hotspot/src/os/aix/vm/jvm_aix.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2013 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -113,7 +113,6 @@ /* Signal definitions */ #define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */ -#define INTERRUPT_SIGNAL SIGUSR1 /* Interruptible I/O support. */ #define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */ #define SHUTDOWN2_SIGNAL SIGINT #define SHUTDOWN3_SIGNAL SIGTERM diff --git a/hotspot/src/os/aix/vm/loadlib_aix.cpp b/hotspot/src/os/aix/vm/loadlib_aix.cpp index e62b5ffff7e..183e2395b21 100644 --- a/hotspot/src/os/aix/vm/loadlib_aix.cpp +++ b/hotspot/src/os/aix/vm/loadlib_aix.cpp @@ -33,153 +33,337 @@ #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif -// 'allocation.inline.hpp' triggers the inclusion of 'inttypes.h' which defines macros -// required by the definitions in 'globalDefinitions.hpp'. But these macros in 'inttypes.h' -// are only defined if '__STDC_FORMAT_MACROS' is defined! -#include "memory/allocation.inline.hpp" -#include "oops/oop.inline.hpp" -#include "runtime/threadCritical.hpp" + +#include "loadlib_aix.hpp" +// for CritSect +#include "misc_aix.hpp" +#include "porting_aix.hpp" #include "utilities/debug.hpp" #include "utilities/ostream.hpp" -#include "loadlib_aix.hpp" -#include "porting_aix.hpp" // For loadquery() #include -/////////////////////////////////////////////////////////////////////////////// -// Implementation for LoadedLibraryModule +// Use raw malloc instead of os::malloc - this code gets used for error reporting. -// output debug info -void LoadedLibraryModule::print(outputStream* os) const { - os->print("%15.15s: text: " INTPTR_FORMAT " - " INTPTR_FORMAT - ", data: " INTPTR_FORMAT " - " INTPTR_FORMAT " ", - shortname, text_from, text_to, data_from, data_to); - os->print(" %s", fullpath); - if (strlen(membername) > 0) { - os->print("(%s)", membername); +// A class to "intern" eternal strings. +// TODO: similar coding exists in AIX version of dladdr and potentially elsewhere: consolidate! +class StringList { + + char** _list; + int _cap; + int _num; + + // Enlarge list. If oom, leave old list intact and return false. + bool enlarge() { + int cap2 = _cap + 64; + char** l2 = (char**) ::realloc(_list, sizeof(char*) * cap2); + if (!l2) { + return false; + } + _list = l2; + _cap = cap2; + return true; + } + + // Append string to end of list. + // Returns NULL if oom. + char* append(const char* s) { + if (_cap == _num) { + if (!enlarge()) { + return NULL; + } + } + assert0(_cap > _num); + char* s2 = ::strdup(s); + if (!s2) { + return NULL; + } + _list[_num] = s2; + trcVerbose("StringDir: added %s at pos %d", s2, _num); + _num ++; + return s2; + } + +public: + + StringList() + : _list(NULL) + , _cap(0) + , _num(0) + {} + + // String is copied into the list; pointer to copy is returned. + // Returns NULL if oom. + char* add (const char* s) { + for (int i = 0; i < _num; i++) { + if (strcmp(_list[i], s) == 0) { + return _list[i]; + } + } + return append(s); + } + +}; + +static StringList g_stringlist; + +////////////////////// + +// Entries are kept in a linked list ordered by text address. Entries are not +// eternal - this list is rebuilt on every reload. +// Note that we do not hand out those entries, but copies of them. + +struct entry_t { + entry_t* next; + loaded_module_t info; +}; + +static void print_entry(const entry_t* e, outputStream* os) { + const loaded_module_t* const lm = &(e->info); + os->print(" %c text: " INTPTR_FORMAT " - " INTPTR_FORMAT + ", data: " INTPTR_FORMAT " - " INTPTR_FORMAT " " + "%s", + (lm->is_in_vm ? '*' : ' '), + lm->text, (uintptr_t)lm->text + lm->text_len, + lm->data, (uintptr_t)lm->data + lm->data_len, + lm->path); + if (lm->member) { + os->print("(%s)", lm->member); } - os->cr(); } +static entry_t* g_first = NULL; -/////////////////////////////////////////////////////////////////////////////// -// Implementation for LoadedLibraries - -// class variables -LoadedLibraryModule LoadedLibraries::tab[MAX_MODULES]; -int LoadedLibraries::num_loaded = 0; - -// Checks whether the address p points to any of the loaded code segments. -// If it does, returns the LoadedLibraryModule entry. If not, returns NULL. -// static -const LoadedLibraryModule* LoadedLibraries::find_for_text_address(const unsigned char* p) { - - if (num_loaded == 0) { - reload(); - } - for (int i = 0; i < num_loaded; i++) { - if (tab[i].is_in_text(p)) { - return &tab[i]; +static entry_t* find_entry_for_text_address(const void* p) { + for (entry_t* e = g_first; e; e = e->next) { + if ((uintptr_t)p >= (uintptr_t)e->info.text && + (uintptr_t)p < ((uintptr_t)e->info.text + e->info.text_len)) { + return e; } } return NULL; } -// Checks whether the address p points to any of the loaded data segments. -// If it does, returns the LoadedLibraryModule entry. If not, returns NULL. -// static -const LoadedLibraryModule* LoadedLibraries::find_for_data_address(const unsigned char* p) { - if (num_loaded == 0) { - reload(); - } - for (int i = 0; i < num_loaded; i++) { - if (tab[i].is_in_data(p)) { - return &tab[i]; +static entry_t* find_entry_for_data_address(const void* p) { + for (entry_t* e = g_first; e; e = e->next) { + if ((uintptr_t)p >= (uintptr_t)e->info.data && + (uintptr_t)p < ((uintptr_t)e->info.data + e->info.data_len)) { + return e; } } return NULL; } -// Rebuild the internal table of LoadedLibraryModule objects -// static -void LoadedLibraries::reload() { - - ThreadCritical cs; - - // discard old content - num_loaded = 0; - - // Call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX. - size_t buf_size = 4096; - char* loadquery_buf = AllocateHeap(buf_size, mtInternal); - - while(loadquery(L_GETINFO, loadquery_buf, buf_size) == -1) { - if (errno == ENOMEM) { - buf_size *= 2; - loadquery_buf = ReallocateHeap(loadquery_buf, buf_size, mtInternal); - } else { - FreeHeap(loadquery_buf); - // Ensure that the uintptr_t pointer is valid - assert(errno != EFAULT, "loadquery: Invalid uintptr_t in info buffer."); - fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno)); - return; - } +// Adds a new entry to the list (ordered by text address ascending). +static void add_entry_to_list(entry_t* e, entry_t** start) { + entry_t* last = NULL; + entry_t* e2 = *start; + while (e2 && e2->info.text < e->info.text) { + last = e2; + e2 = e2->next; } + if (last) { + last->next = e; + } else { + *start = e; + } + e->next = e2; +} - // Iterate over the loadquery result. For details see sys/ldr.h on AIX. - const struct ld_info* p = (struct ld_info*) loadquery_buf; +static void free_entry_list(entry_t** start) { + entry_t* e = *start; + while (e) { + entry_t* const e2 = e->next; + ::free(e); + e = e2; + } + *start = NULL; +} - // Ensure we have all loaded libs. - bool all_loaded = false; - while(num_loaded < MAX_MODULES) { - LoadedLibraryModule& mod = tab[num_loaded]; - mod.text_from = (const unsigned char*) p->ldinfo_textorg; - mod.text_to = (const unsigned char*) (((char*)p->ldinfo_textorg) + p->ldinfo_textsize); - mod.data_from = (const unsigned char*) p->ldinfo_dataorg; - mod.data_to = (const unsigned char*) (((char*)p->ldinfo_dataorg) + p->ldinfo_datasize); - sprintf(mod.fullpath, "%.*s", sizeof(mod.fullpath), p->ldinfo_filename); - // do we have a member name as well (see ldr.h)? - const char* p_mbr_name = p->ldinfo_filename + strlen(p->ldinfo_filename) + 1; - if (*p_mbr_name) { - sprintf(mod.membername, "%.*s", sizeof(mod.membername), p_mbr_name); + +// Rebuild the internal module table. If an error occurs, old table remains +// unchanged. +static bool reload_table() { + + bool rc = false; + + trcVerbose("reload module table..."); + + entry_t* new_list = NULL; + const struct ld_info* ldi = NULL; + + // Call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX. loadquery + // requires a large enough buffer. + uint8_t* buffer = NULL; + size_t buflen = 1024; + for (;;) { + buffer = (uint8_t*) ::realloc(buffer, buflen); + if (loadquery(L_GETINFO, buffer, buflen) == -1) { + if (errno == ENOMEM) { + buflen *= 2; + } else { + trcVerbose("loadquery failed (%d)", errno); + goto cleanup; + } } else { - mod.membername[0] = '\0'; - } - - // fill in the short name - const char* p_slash = strrchr(mod.fullpath, '/'); - if (p_slash) { - sprintf(mod.shortname, "%.*s", sizeof(mod.shortname), p_slash + 1); - } else { - sprintf(mod.shortname, "%.*s", sizeof(mod.shortname), mod.fullpath); - } - num_loaded ++; - - // next entry... - if (p->ldinfo_next) { - p = (struct ld_info*)(((char*)p) + p->ldinfo_next); - } else { - all_loaded = true; break; } } - FreeHeap(loadquery_buf); + trcVerbose("loadquery buffer size is %llu.", buflen); - // Ensure we have all loaded libs - assert(all_loaded, "loadquery returned more entries then expected. Please increase MAX_MODULES"); + // Iterate over the loadquery result. For details see sys/ldr.h on AIX. + ldi = (struct ld_info*) buffer; + + for (;;) { + + entry_t* e = (entry_t*) ::malloc(sizeof(entry_t)); + if (!e) { + trcVerbose("OOM."); + goto cleanup; + } + + memset(e, 0, sizeof(entry_t)); + + e->info.text = ldi->ldinfo_textorg; + e->info.text_len = ldi->ldinfo_textsize; + e->info.data = ldi->ldinfo_dataorg; + e->info.data_len = ldi->ldinfo_datasize; + + e->info.path = g_stringlist.add(ldi->ldinfo_filename); + if (!e->info.path) { + trcVerbose("OOM."); + goto cleanup; + } + + // Extract short name + { + const char* p = strrchr(e->info.path, '/'); + if (p) { + p ++; + e->info.shortname = p; + } else { + e->info.shortname = e->info.path; + } + } + + // Do we have a member name as well (see ldr.h)? + const char* p_mbr_name = + ldi->ldinfo_filename + strlen(ldi->ldinfo_filename) + 1; + if (*p_mbr_name) { + e->info.member = g_stringlist.add(p_mbr_name); + if (!e->info.member) { + trcVerbose("OOM."); + goto cleanup; + } + } else { + e->info.member = NULL; + } + + if (strcmp(e->info.shortname, "libjvm.so") == 0) { + // Note that this, theoretically, is fuzzy. We may accidentally contain + // more than one libjvm.so. But that is improbable, so lets go with this + // solution. + e->info.is_in_vm = true; + } + + trcVerbose("entry: %p %llu, %p %llu, %s %s %s, %d", + e->info.text, e->info.text_len, + e->info.data, e->info.data_len, + e->info.path, e->info.shortname, + (e->info.member ? e->info.member : "NULL"), + e->info.is_in_vm + ); + + // Add to list. + add_entry_to_list(e, &new_list); + + // Next entry... + if (ldi->ldinfo_next) { + ldi = (struct ld_info*)(((char*)ldi) + ldi->ldinfo_next); + } else { + break; + } + } + + // We are done. All is well. Free old list and swap to new one. + if (g_first) { + free_entry_list(&g_first); + } + g_first = new_list; + new_list = NULL; + + rc = true; + +cleanup: + + if (new_list) { + free_entry_list(&new_list); + } + + ::free(buffer); + + return rc; } // end LoadedLibraries::reload() -// output loaded libraries table -//static -void LoadedLibraries::print(outputStream* os) { +/////////////////////////////////////////////////////////////////////////////// +// Externals - for (int i = 0; i < num_loaded; i++) { - tab[i].print(os); - } +static MiscUtils::CritSect g_cs; +// Rebuild the internal module table. If an error occurs, old table remains +// unchanged. +bool LoadedLibraries::reload() { + MiscUtils::AutoCritSect lck(&g_cs); + return reload_table(); +} + +void LoadedLibraries::print(outputStream* os) { + MiscUtils::AutoCritSect lck(&g_cs); + if (!g_first) { + reload_table(); + } + for (entry_t* e = g_first; e; e = e->next) { + print_entry(e, os); + os->cr(); + } +} + +bool LoadedLibraries::find_for_text_address(const void* p, + loaded_module_t* info) { + MiscUtils::AutoCritSect lck(&g_cs); + if (!g_first) { + reload_table(); + } + const entry_t* const e = find_entry_for_text_address(p); + if (e) { + if (info) { + *info = e->info; + } + return true; + } + return false; +} + + +bool LoadedLibraries::find_for_data_address ( + const void* p, + loaded_module_t* info // optional. can be NULL: +) { + MiscUtils::AutoCritSect lck(&g_cs); + if (!g_first) { + reload_table(); + } + const entry_t* const e = find_entry_for_data_address(p); + if (e) { + if (info) { + *info = e->info; + } + return true; + } + return false; } diff --git a/hotspot/src/os/aix/vm/loadlib_aix.hpp b/hotspot/src/os/aix/vm/loadlib_aix.hpp index 2f6c2008f2a..b619141cd54 100644 --- a/hotspot/src/os/aix/vm/loadlib_aix.hpp +++ b/hotspot/src/os/aix/vm/loadlib_aix.hpp @@ -26,73 +26,47 @@ // Loadlib_aix.cpp contains support code for analysing the memory // layout of loaded binaries in ones own process space. // -// It is needed, among other things, to provide a dladdr() emulation, because -// that one is not provided by AIX +// It is needed, among other things, to provide dladdr(3), which is +// missing on AIX. #ifndef OS_AIX_VM_LOADLIB_AIX_HPP #define OS_AIX_VM_LOADLIB_AIX_HPP +#include + class outputStream; -// This class holds information about a single loaded library module. +// Struct holds information about a single loaded library module. // Note that on AIX, a single library can be spread over multiple -// uintptr_t range on a module base, eg. +// uintptr_t ranges on a module base, eg. // libC.a(shr3_64.o) or libC.a(shrcore_64.o). -class LoadedLibraryModule { - friend class LoadedLibraries; +// Note: all pointers to strings (path, member) point to strings which are immortal. +struct loaded_module_t { - char fullpath[512]; // eg /usr/lib/libC.a - char shortname[30]; // eg libC.a - char membername[30]; // eg shrcore_64.o - const unsigned char* text_from; - const unsigned char* text_to; - const unsigned char* data_from; - const unsigned char* data_to; + // Points to the full path of the lodaed module, e.g. + // "/usr/lib/libC.a". + const char* path; - public: + // Host library name without path + const char* shortname; - const char* get_fullpath() const { - return fullpath; - } - const char* get_shortname() const { - return shortname; - } - const char* get_membername() const { - return membername; - } + // Points to the object file (AIX specific stuff) + // e.g "shrcore_64.o". + const char* member; - // text_from, text_to: returns the range of the text (code) - // segment for that module - const unsigned char* get_text_from() const { - return text_from; - } - const unsigned char* get_text_to() const { - return text_to; - } + // Text area from, to + const void* text; + size_t text_len; - // data_from/data_to: returns the range of the data - // segment for that module - const unsigned char* get_data_from() const { - return data_from; - } - const unsigned char* get_data_to() const { - return data_to; - } + // Data area from, to + const void* data; + size_t data_len; - // returns true if the - bool is_in_text(const unsigned char* p) const { - return p >= text_from && p < text_to ? true : false; - } + // True if this module is part of the vm. + bool is_in_vm; - bool is_in_data(const unsigned char* p) const { - return p >= data_from && p < data_to ? true : false; - } - - // output debug info - void print(outputStream* os) const; - -}; // end LoadedLibraryModule +}; // This class is a singleton holding a map of all loaded binaries // in the AIX process space. @@ -100,29 +74,31 @@ class LoadedLibraries // : AllStatic (including allocation.hpp just for AllStatic is overkill.) { - private: - - enum {MAX_MODULES = 100}; - static LoadedLibraryModule tab[MAX_MODULES]; - static int num_loaded; - public: - // rebuild the internal table of LoadedLibraryModule objects - static void reload(); + // Rebuild the internal module table. If an error occurs, internal module + // table remains untouched. + static bool reload(); - // checks whether the address p points to any of the loaded code segments. - // If it does, returns the LoadedLibraryModule entry. If not, returns NULL. - static const LoadedLibraryModule* find_for_text_address(const unsigned char* p); + // Check whether the given address points into the text segment of a + // loaded module. Return true if this is the case. + // Optionally, information about the module is returned (info) + static bool find_for_text_address ( + const void* p, + loaded_module_t* info // Optional, leave NULL if not needed. + ); - // checks whether the address p points to any of the loaded data segments. - // If it does, returns the LoadedLibraryModule entry. If not, returns NULL. - static const LoadedLibraryModule* find_for_data_address(const unsigned char* p); + // Check whether the given address points into the data segment of a + // loaded module. Return true if this is the case. + // Optionally, information about the module is returned (info) + static bool find_for_data_address ( + const void* p, + loaded_module_t* info // Optional, leave NULL if not needed. + ); - // output debug info + // Output debug info static void print(outputStream* os); -}; // end LoadedLibraries - +}; #endif // OS_AIX_VM_LOADLIB_AIX_HPP diff --git a/hotspot/src/os/aix/vm/misc_aix.cpp b/hotspot/src/os/aix/vm/misc_aix.cpp new file mode 100644 index 00000000000..daad0e19c36 --- /dev/null +++ b/hotspot/src/os/aix/vm/misc_aix.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2015 SAP AG. 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 "misc_aix.hpp" +#include "runtime/stubRoutines.hpp" + +#include + +void MiscUtils::init_critsect(MiscUtils::critsect_t* cs) { + const int rc = pthread_mutex_init(cs, NULL); + assert0(rc == 0); +} + +void MiscUtils::free_critsect(MiscUtils::critsect_t* cs) { + const int rc = pthread_mutex_destroy(cs); + assert0(rc == 0); +} + +void MiscUtils::enter_critsect(MiscUtils::critsect_t* cs) { + const int rc = pthread_mutex_lock(cs); + assert0(rc == 0); +} + +void MiscUtils::leave_critsect(MiscUtils::critsect_t* cs) { + const int rc = pthread_mutex_unlock(cs); + assert0(rc == 0); +} + +bool MiscUtils::is_readable_pointer(const void* p) { + if (!CanUseSafeFetch32()) { + return true; + } + int* const aligned = (int*) align_size_down((intptr_t)p, 4); + int cafebabe = 0xcafebabe; + int deadbeef = 0xdeadbeef; + return (SafeFetch32(aligned, cafebabe) != cafebabe) || + (SafeFetch32(aligned, deadbeef) != deadbeef); +} + + diff --git a/hotspot/src/os/aix/vm/misc_aix.hpp b/hotspot/src/os/aix/vm/misc_aix.hpp new file mode 100644 index 00000000000..8b66d2e040b --- /dev/null +++ b/hotspot/src/os/aix/vm/misc_aix.hpp @@ -0,0 +1,101 @@ +/* + * Copyright 2012, 2015 SAP AG. 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 OS_AIX_VM_MISC_AIX_HPP +#define OS_AIX_VM_MISC_AIX_HPP + +// misc_aix.hpp, misc_aix.cpp: convenience functions needed for the OpenJDK AIX +// port. +#include "utilities/globalDefinitions.hpp" + +#include + +// Trace if verbose to tty. +#define trcVerbose(fmt, ...) { \ + if (Verbose) { \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fputc('\n', stderr); fflush(stderr); \ + } \ +} +#define ERRBYE(s) { trcVerbose(s); return -1; } +#define trc(fmt, ...) + +#define assert0(b) assert((b), "") +#define guarantee0(b) guarantee((b), "") +template bool is_aligned_to(T1 what, T2 alignment) { + return (((uintx)(what)) & (((uintx)(alignment)) - 1)) == 0 ? true : false; +} + +// CritSect: simple critical section implementation using pthread mutexes. +namespace MiscUtils { + typedef pthread_mutex_t critsect_t; + + void init_critsect(MiscUtils::critsect_t* cs); + void free_critsect(MiscUtils::critsect_t* cs); + void enter_critsect(MiscUtils::critsect_t* cs); + void leave_critsect(MiscUtils::critsect_t* cs); + + // Need to wrap this in an object because we need to dynamically initialize + // critical section (because of windows, where there is no way to initialize + // a CRITICAL_SECTION statically. On Unix, we could use + // PTHREAD_MUTEX_INITIALIZER). + + // Note: The critical section does NOT get cleaned up in the destructor. That is + // by design: the CritSect class is only ever used as global objects whose + // lifetime spans the whole VM life; in that context we don't want the lock to + // be cleaned up when global C++ objects are destroyed, but to continue to work + // correctly right to the very end of the process life. + class CritSect { + critsect_t _cs; + public: + CritSect() { init_critsect(&_cs); } + //~CritSect() { free_critsect(&_cs); } + void enter() { enter_critsect(&_cs); } + void leave() { leave_critsect(&_cs); } + }; + + class AutoCritSect { + CritSect* const _pcsobj; + public: + AutoCritSect(CritSect* pcsobj) + : _pcsobj(pcsobj) + { + _pcsobj->enter(); + } + ~AutoCritSect() { + _pcsobj->leave(); + } + }; + + // Returns true if pointer can be dereferenced without triggering a segment + // violation. Returns false if pointer is invalid. + // Note: Depends on stub routines; prior to stub routine generation, will + // always return true. Use CanUseSafeFetch32 to handle this case. + bool is_readable_pointer(const void* p); + +} + +#endif // OS_AIX_VM_MISC_AIX_HPP + diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index fb3ea648414..9bc5ab02f06 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -40,6 +40,7 @@ #include "loadlib_aix.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" +#include "misc_aix.hpp" #include "mutex_aix.inline.hpp" #include "oops/oop.inline.hpp" #include "os_aix.inline.hpp" @@ -159,23 +160,10 @@ typedef stackslot_t* stackptr_t; #define PV_8_Compat 0x308000 /* Power PC 8 */ #endif -#define trcVerbose(fmt, ...) { /* PPC port */ \ - if (Verbose) { \ - fprintf(stderr, fmt, ##__VA_ARGS__); \ - fputc('\n', stderr); fflush(stderr); \ - } \ -} -#define trc(fmt, ...) /* PPC port */ - -#define ERRBYE(s) { \ - trcVerbose(s); \ - return -1; \ -} - // Query dimensions of the stack of the calling thread. static bool query_stack_dimensions(address* p_stack_base, size_t* p_stack_size); -// function to check a given stack pointer against given stack limits +// Function to check a given stack pointer against given stack limits. inline bool is_valid_stackpointer(stackptr_t sp, stackptr_t stack_base, size_t stack_size) { if (((uintptr_t)sp) & 0x7) { return false; @@ -189,7 +177,7 @@ inline bool is_valid_stackpointer(stackptr_t sp, stackptr_t stack_base, size_t s return true; } -// returns true if function is a valid codepointer +// Returns true if function is a valid codepointer. inline bool is_valid_codepointer(codeptr_t p) { if (!p) { return false; @@ -197,7 +185,7 @@ inline bool is_valid_codepointer(codeptr_t p) { if (((uintptr_t)p) & 0x3) { return false; } - if (LoadedLibraries::find_for_text_address((address)p) == NULL) { + if (!LoadedLibraries::find_for_text_address(p, NULL)) { return false; } return true; @@ -1387,26 +1375,15 @@ bool os::address_is_in_vm(address addr) { // Input could be a real pc or a function pointer literal. The latter // would be a function descriptor residing in the data segment of a module. - - const LoadedLibraryModule* lib = LoadedLibraries::find_for_text_address(addr); - if (lib) { - if (strcmp(lib->get_shortname(), "libjvm.so") == 0) { - return true; - } else { - return false; - } + loaded_module_t lm; + if (LoadedLibraries::find_for_text_address(addr, &lm) != NULL) { + return lm.is_in_vm; + } else if (LoadedLibraries::find_for_data_address(addr, &lm) != NULL) { + return lm.is_in_vm; } else { - lib = LoadedLibraries::find_for_data_address(addr); - if (lib) { - if (strcmp(lib->get_shortname(), "libjvm.so") == 0) { - return true; - } else { - return false; - } - } else { - return false; - } + return false; } + } // Resolve an AIX function descriptor literal to a code pointer. @@ -1418,21 +1395,18 @@ bool os::address_is_in_vm(address addr) { // NULL is returned. static address resolve_function_descriptor_to_code_pointer(address p) { - const LoadedLibraryModule* lib = LoadedLibraries::find_for_text_address(p); - if (lib) { - // its a real code pointer + if (LoadedLibraries::find_for_text_address(p, NULL) != NULL) { + // It is a real code pointer. return p; - } else { - lib = LoadedLibraries::find_for_data_address(p); - if (lib) { - // pointer to data segment, potential function descriptor - address code_entry = (address)(((FunctionDescriptor*)p)->entry()); - if (LoadedLibraries::find_for_text_address(code_entry)) { - // Its a function descriptor - return code_entry; - } + } else if (LoadedLibraries::find_for_data_address(p, NULL) != NULL) { + // Pointer to data segment, potential function descriptor. + address code_entry = (address)(((FunctionDescriptor*)p)->entry()); + if (LoadedLibraries::find_for_text_address(code_entry, NULL) != NULL) { + // It is a function descriptor. + return code_entry; } } + return NULL; } @@ -1461,7 +1435,6 @@ static int getModuleName(codeptr_t pc, // [in] program counte char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages ) { - // initialize output parameters if (p_name && namelen > 0) { *p_name = '\0'; } @@ -1469,16 +1442,15 @@ static int getModuleName(codeptr_t pc, // [in] program counte *p_errmsg = '\0'; } - const LoadedLibraryModule* const lib = LoadedLibraries::find_for_text_address((address)pc); - if (lib) { - if (p_name && namelen > 0) { - sprintf(p_name, "%.*s", namelen, lib->get_shortname()); + if (p_name && namelen > 0) { + loaded_module_t lm; + if (LoadedLibraries::find_for_text_address(pc, &lm) != NULL) { + strncpy(p_name, lm.shortname, namelen); + p_name[namelen - 1] = '\0'; } return 0; } - trcVerbose("pc outside any module"); - return -1; } @@ -1690,7 +1662,6 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { print_signal_handler(st, SIGPIPE, buf, buflen); print_signal_handler(st, SIGXFSZ, buf, buflen); print_signal_handler(st, SIGILL , buf, buflen); - print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen); print_signal_handler(st, SR_signum, buf, buflen); print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen); print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); @@ -3309,7 +3280,6 @@ void os::run_periodic_checks() { } DO_SIGNAL_CHECK(SR_signum); - DO_SIGNAL_CHECK(INTERRUPT_SIGNAL); } typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *); @@ -3351,10 +3321,6 @@ void os::Aix::check_signal_handler(int sig) { jvmHandler = (address)user_handler(); break; - case INTERRUPT_SIGNAL: - jvmHandler = CAST_FROM_FN_PTR(address, SIG_DFL); - break; - default: if (sig == SR_signum) { jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler); @@ -3787,18 +3753,11 @@ bool os::find(address addr, outputStream* st) { st->print(PTR_FORMAT ": ", addr); - const LoadedLibraryModule* lib = LoadedLibraries::find_for_text_address(addr); - if (lib) { - lib->print(st); + loaded_module_t lm; + if (LoadedLibraries::find_for_text_address(addr, &lm) != NULL || + LoadedLibraries::find_for_data_address(addr, &lm) != NULL) { + st->print("%s", lm.path); return true; - } else { - lib = LoadedLibraries::find_for_data_address(addr); - if (lib) { - lib->print(st); - return true; - } else { - st->print_cr("(outside any module)"); - } } return false; @@ -3811,7 +3770,7 @@ bool os::find(address addr, outputStream* st) { // able to use structured exception handling (thread-local exception filters) // on, e.g., Win32. void -os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, +os::os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& method, JavaCallArguments* args, Thread* thread) { f(value, method, args, thread); } @@ -3965,9 +3924,6 @@ int os::available(int fd, jlong *bytes) { if (::fstat64(fd, &buf64) >= 0) { mode = buf64.st_mode; if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { - // XXX: is the following call interruptible? If so, this might - // need to go through the INTERRUPT_IO() wrapper as for other - // blocking, interruptible calls in this file. int n; if (::ioctl(fd, FIONREAD, &n) >= 0) { *bytes = n; diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp index 2e3cfdd0243..90dc6cc7e54 100644 --- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp @@ -201,6 +201,7 @@ static pid_t filename_to_pid(const char* filename) { // the backing store files. Returns true if the directory is considered // a secure location. Returns false if the statbuf is a symbolic link or // if an error occurred. +// static bool is_statbuf_secure(struct stat *statp) { if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) { // The path represents a link or some non-directory file type, @@ -209,15 +210,18 @@ static bool is_statbuf_secure(struct stat *statp) { return false; } // We have an existing directory, check if the permissions are safe. + // if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) { // The directory is open for writing and could be subjected // to a symlink or a hard link attack. Declare it insecure. + // return false; } - // See if the uid of the directory matches the effective uid of the process. - // - if (statp->st_uid != geteuid()) { + // If user is not root then see if the uid of the directory matches the effective uid of the process. + uid_t euid = geteuid(); + if ((euid != 0) && (statp->st_uid != euid)) { // The directory was not created by this user, declare it insecure. + // return false; } return true; @@ -228,6 +232,7 @@ static bool is_statbuf_secure(struct stat *statp) { // the backing store files. Returns true if the directory exists // and is considered a secure location. Returns false if the path // is a symbolic link or if an error occurred. +// static bool is_directory_secure(const char* path) { struct stat statbuf; int result = 0; diff --git a/hotspot/src/os/aix/vm/porting_aix.cpp b/hotspot/src/os/aix/vm/porting_aix.cpp index 8ccdd127e7f..d5e8e881872 100644 --- a/hotspot/src/os/aix/vm/porting_aix.cpp +++ b/hotspot/src/os/aix/vm/porting_aix.cpp @@ -23,11 +23,13 @@ */ #include "asm/assembler.hpp" +#include "loadlib_aix.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" -#include "runtime/os.hpp" -#include "loadlib_aix.hpp" +// For CritSect +#include "misc_aix.hpp" #include "porting_aix.hpp" +#include "runtime/os.hpp" #include "utilities/debug.hpp" #include @@ -45,23 +47,6 @@ #define PTRDIFF_BYTES(p1,p2) (((ptrdiff_t)p1) - ((ptrdiff_t)p2)) -// Align a pointer without having to cast. -inline char* align_ptr_up(char* ptr, intptr_t alignment) { - return (char*) align_size_up((intptr_t)ptr, alignment); -} - -// Trace if verbose to tty. -// I use these now instead of the Xtrace system because the latter is -// not available at init time, hence worthless. Until we fix this, all -// tracing here is done with -XX:+Verbose. -#define trcVerbose(fmt, ...) { \ - if (Verbose) { \ - fprintf(stderr, fmt, ##__VA_ARGS__); \ - fputc('\n', stderr); fflush(stderr); \ - } \ -} -#define ERRBYE(s) { trcVerbose(s); return -1; } - // Unfortunately, the interface of dladdr makes the implementator // responsible for maintaining memory for function name/library // name. I guess this is because most OS's keep those values as part @@ -139,18 +124,37 @@ extern "C" int getFuncName( ERRBYE("invalid program counter"); } + // We see random but frequent crashes in this function since some months mainly on shutdown + // (-XX:+DumpInfoAtExit). It appears the page we are reading is randomly disappearing while + // we read it (?). + // As the pc cannot be trusted to be anything sensible lets make all reads via SafeFetch. Also + // bail if this is not a text address right now. + if (!LoadedLibraries::find_for_text_address(pc, NULL)) { + ERRBYE("not a text address"); + } + + // .. (Note that is_readable_pointer returns true if safefetch stubs are not there yet; + // in that case I try reading the traceback table unsafe - I rather risk secondary crashes in + // error files than not having a callstack.) +#define CHECK_POINTER_READABLE(p) \ + if (!MiscUtils::is_readable_pointer(p)) { \ + ERRBYE("pc not readable"); \ + } + codeptr_t pc2 = pc; - // make sure the pointer is word aligned. + // Make sure the pointer is word aligned. pc2 = (codeptr_t) align_ptr_up((char*)pc2, 4); + CHECK_POINTER_READABLE(pc2) // Find start of traceback table. // (starts after code, is marked by word-aligned (32bit) zeros) while ((*pc2 != NULL) && (searchcount++ < MAX_FUNC_SEARCH_LEN)) { + CHECK_POINTER_READABLE(pc2) pc2++; } if (*pc2 != 0) { - ERRBYE("could not find traceback table within 5000 bytes of program counter"); + ERRBYE("no traceback table found"); } // // Set up addressability to the traceback table @@ -162,7 +166,7 @@ extern "C" int getFuncName( if (tb->tb.lang >= 0xf && tb->tb.lang <= 0xfb) { // Language specifiers, go from 0 (C) to 14 (Objective C). // According to spec, 0xf-0xfa reserved, 0xfb-0xff reserved for ibm. - ERRBYE("not a traceback table"); + ERRBYE("no traceback table found"); } // Existence of fields in the tbtable extension are contingent upon @@ -173,6 +177,8 @@ extern "C" int getFuncName( if (tb->tb.fixedparms != 0 || tb->tb.floatparms != 0) pc2++; + CHECK_POINTER_READABLE(pc2) + if (tb->tb.has_tboff == TRUE) { // I want to know the displacement @@ -182,7 +188,7 @@ extern "C" int getFuncName( // Weed out the cases where we did find the wrong traceback table. if (pc < start_of_procedure) { - ERRBYE("could not find (the real) traceback table within 5000 bytes of program counter"); + ERRBYE("no traceback table found"); } // return the displacement @@ -204,15 +210,24 @@ extern "C" int getFuncName( if (tb->tb.has_ctl == TRUE) pc2 += (*pc2) + 1; // don't care + CHECK_POINTER_READABLE(pc2) + // // return function name if it exists. // if (p_name && namelen > 0) { if (tb->tb.name_present) { + // Copy name from text because it may not be zero terminated. + // 256 is good enough for most cases; do not use large buffers here. char buf[256]; const short l = MIN2(*((short*)pc2), sizeof(buf) - 1); - memcpy(buf, (char*)pc2 + sizeof(short), l); - buf[l] = '\0'; + // Be very careful. + int i = 0; char* const p = (char*)pc2 + sizeof(short); + while (i < l && MiscUtils::is_readable_pointer(p + i)) { + buf[i] = p[i]; + i++; + } + buf[i] = '\0'; p_name[0] = '\0'; @@ -275,7 +290,8 @@ int dladdr(void* addr, Dl_info* info) { info->dli_saddr = NULL; address p = (address) addr; - const LoadedLibraryModule* lib = NULL; + loaded_module_t lm; + bool found = false; enum { noclue, code, data } type = noclue; @@ -284,28 +300,28 @@ int dladdr(void* addr, Dl_info* info) { // Note: input address may be a function. I accept both a pointer to // the entry of a function and a pointer to the function decriptor. // (see ppc64 ABI) - lib = LoadedLibraries::find_for_text_address(p); - if (lib) { + found = LoadedLibraries::find_for_text_address(p, &lm); + if (found) { type = code; } - if (!lib) { + if (!found) { // Not a pointer into any text segment. Is it a function descriptor? const FunctionDescriptor* const pfd = (const FunctionDescriptor*) p; p = pfd->entry(); if (p) { - lib = LoadedLibraries::find_for_text_address(p); - if (lib) { + found = LoadedLibraries::find_for_text_address(p, &lm); + if (found) { type = code; } } } - if (!lib) { + if (!found) { // Neither direct code pointer nor function descriptor. A data ptr? p = (address)addr; - lib = LoadedLibraries::find_for_data_address(p); - if (lib) { + found = LoadedLibraries::find_for_data_address(p, &lm); + if (found) { type = data; } } @@ -313,12 +329,10 @@ int dladdr(void* addr, Dl_info* info) { // If we did find the shared library this address belongs to (either // code or data segment) resolve library path and, if possible, the // symbol name. - if (lib) { - const char* const interned_libpath = - dladdr_fixed_strings.intern(lib->get_fullpath()); - if (interned_libpath) { - info->dli_fname = interned_libpath; - } + if (found) { + + // No need to intern the libpath, that one is already interned one layer below. + info->dli_fname = lm.path; if (type == code) { @@ -328,7 +342,7 @@ int dladdr(void* addr, Dl_info* info) { int displacement = 0; if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement, - NULL, NULL, 0, true /* demangle */) == 0) { + NULL, NULL, 0, false) == 0) { if (funcname[0] != '\0') { const char* const interned = dladdr_fixed_strings.intern(funcname); info->dli_sname = interned; diff --git a/hotspot/src/os/aix/vm/porting_aix.hpp b/hotspot/src/os/aix/vm/porting_aix.hpp index 0309233e120..6a004df5b8b 100644 --- a/hotspot/src/os/aix/vm/porting_aix.hpp +++ b/hotspot/src/os/aix/vm/porting_aix.hpp @@ -27,13 +27,6 @@ #include -// PPC port only: -#define assert0(b) assert( (b), "" ) -#define guarantee0(b) assert( (b), "" ) -template bool is_aligned_to(T1 what, T2 alignment) { - return ( ((uintx)(what)) & (((uintx)(alignment)) - 1) ) == 0 ? true : false; -} - // Header file to contain porting-relevant code which does not have a // home anywhere else and which can not go into os_.h because // that header is included inside the os class definition, hence all @@ -68,14 +61,10 @@ extern "C" #endif int dladdr(void *addr, Dl_info *info); - -// The semantics in this file are thus that codeptr_t is a *real code ptr*. -// This means that any function taking codeptr_t as arguments will assume -// a real codeptr and won't handle function descriptors (eg getFuncName), -// whereas functions taking address as args will deal with function -// descriptors (eg os::dll_address_to_library_name). typedef unsigned int* codeptr_t; +struct tbtable; + // helper function - given a program counter, tries to locate the traceback table and // returns info from it (like, most importantly, function name, displacement of the // pc inside the function, and the traceback table itself. @@ -87,65 +76,9 @@ int getFuncName( char* p_name, size_t namelen, // [out] optional: user provided buffer for the function name int* p_displacement, // [out] optional: displacement const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further information - char* p_errmsg, size_t errmsglen,// [out] optional: user provided buffer for error messages - bool demangle = true // [in] whether to demangle the name + char* p_errmsg, size_t errmsglen, // [out] optional: user provided buffer for error messages + bool demangle // [in] whether to demangle the name ); -// ------------------------------------------------------------------------- - -// A simple critical section which shall be based upon OS critical -// sections (CRITICAL_SECTION resp. Posix Mutex) and nothing else. - -#include - -namespace MiscUtils { - typedef pthread_mutex_t critsect_t; - - inline void init_critsect(MiscUtils::critsect_t* cs) { - pthread_mutex_init(cs, NULL); - } - inline void free_critsect(MiscUtils::critsect_t* cs) { - pthread_mutex_destroy(cs); - } - inline void enter_critsect(MiscUtils::critsect_t* cs) { - pthread_mutex_lock(cs); - } - inline void leave_critsect(MiscUtils::critsect_t* cs) { - pthread_mutex_unlock(cs); - } - - // Need to wrap this in an object because we need to dynamically initialize - // critical section (because of windows, where there is no way to initialize - // a CRITICAL_SECTION statically. On Unix, we could use - // PTHREAD_MUTEX_INITIALIZER) - - // Note: The critical section does NOT get cleaned up in the destructor. That is - // by design: the CritSect class is only ever used as global objects whose - // lifetime spans the whole VM life; in that context we don't want the lock to - // be cleaned up when global C++ objects are destroyed, but to continue to work - // correctly right to the very end of the process life. - class CritSect { - critsect_t _cs; - public: - CritSect() { init_critsect(&_cs); } - //~CritSect() { free_critsect(&_cs); } - void enter() { enter_critsect(&_cs); } - void leave() { leave_critsect(&_cs); } - }; - - class AutoCritSect { - CritSect* const _pcsobj; - public: - AutoCritSect(CritSect* pcsobj) - : _pcsobj(pcsobj) - { - _pcsobj->enter(); - } - ~AutoCritSect() { - _pcsobj->leave(); - } - }; - -} - #endif // OS_AIX_VM_PORTING_AIX_HPP + diff --git a/hotspot/src/os/bsd/dtrace/libjvm_db.c b/hotspot/src/os/bsd/dtrace/libjvm_db.c index 87a9afe24ff..7a7105c1b25 100644 --- a/hotspot/src/os/bsd/dtrace/libjvm_db.c +++ b/hotspot/src/os/bsd/dtrace/libjvm_db.c @@ -834,7 +834,7 @@ line_number_from_bci(jvm_agent_t* J, Vframe_t *vf) if (stream_bci == vf->bci) { /* perfect match */ if (debug > 2) - fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line); + fprintf(stderr, "\t line_number_from_bci: END: exact line: %d \n\n", vf->line); vf->line = stream_line; return PS_OK; } else { @@ -843,14 +843,14 @@ line_number_from_bci(jvm_agent_t* J, Vframe_t *vf) best_bci = stream_bci; vf->line = stream_line; if (debug > 2) { - fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n", + fprintf(stderr, "\t line_number_from_bci: best_bci: %d, best_line: %d\n", best_bci, vf->line); } } } } if (debug > 2) - fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line); + fprintf(stderr, "\t line_number_from_bci: END: line: %d \n\n", vf->line); return PS_OK; fail: @@ -1002,7 +1002,7 @@ static int scopeDesc_chain(Nmethod_t *N) { err = line_number_from_bci(N->J, vf); CHECK_FAIL(err); if (debug > 2) { - fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n", + fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %d\n", vf->method, vf->line); } } @@ -1338,7 +1338,7 @@ int Jget_vframe(jvm_agent_t* J, int vframe_no, jframe->bci = vf->bci; jframe->line = vf->line; if (debug) { - fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n", + fprintf(stderr, "\t Jget_vframe: method name: %s, line: %d\n", name, vf->line); } return PS_OK; diff --git a/hotspot/src/os/bsd/vm/jvm_bsd.cpp b/hotspot/src/os/bsd/vm/jvm_bsd.cpp index a8286313588..e2e140e2055 100644 --- a/hotspot/src/os/bsd/vm/jvm_bsd.cpp +++ b/hotspot/src/os/bsd/vm/jvm_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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,7 +47,6 @@ JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler)) : handler; switch (sig) { /* The following are already used by the VM. */ - case INTERRUPT_SIGNAL: case SIGFPE: case SIGILL: case SIGSEGV: diff --git a/hotspot/src/os/bsd/vm/jvm_bsd.h b/hotspot/src/os/bsd/vm/jvm_bsd.h index 472269dd5c6..f099198d1b5 100644 --- a/hotspot/src/os/bsd/vm/jvm_bsd.h +++ b/hotspot/src/os/bsd/vm/jvm_bsd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -107,7 +107,6 @@ /* Signal definitions */ #define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */ -#define INTERRUPT_SIGNAL SIGUSR1 /* Interruptible I/O support. */ #define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */ #define SHUTDOWN2_SIGNAL SIGINT #define SHUTDOWN3_SIGNAL SIGTERM diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index cce3906e0c9..70eef822955 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -440,6 +440,10 @@ void os::init_system_properties_values() { if (pslash != NULL) { *pslash = '\0'; // Get rid of /{client|server|hotspot}. } +#ifdef STATIC_BUILD + strcat(buf, "/lib"); +#endif + Arguments::set_dll_dir(buf); if (pslash != NULL) { @@ -1388,6 +1392,9 @@ bool os::dll_address_to_library_name(address addr, char* buf, #ifdef __APPLE__ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { +#ifdef STATIC_BUILD + return os::get_default_process_handle(); +#else void * result= ::dlopen(filename, RTLD_LAZY); if (result != NULL) { // Successful loading @@ -1399,9 +1406,13 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { ebuf[ebuflen-1]='\0'; return NULL; +#endif // STATIC_BUILD } #else void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { +#ifdef STATIC_BUILD + return os::get_default_process_handle(); +#else void * result= ::dlopen(filename, RTLD_LAZY); if (result != NULL) { // Successful loading @@ -1574,6 +1585,7 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { } return NULL; +#endif // STATIC_BUILD } #endif // !__APPLE__ @@ -1765,7 +1777,6 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { print_signal_handler(st, SIGPIPE, buf, buflen); print_signal_handler(st, SIGXFSZ, buf, buflen); print_signal_handler(st, SIGILL , buf, buflen); - print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen); print_signal_handler(st, SR_signum, buf, buflen); print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen); print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); @@ -3333,7 +3344,6 @@ void os::run_periodic_checks() { } DO_SIGNAL_CHECK(SR_signum); - DO_SIGNAL_CHECK(INTERRUPT_SIGNAL); } typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *); @@ -3379,10 +3389,6 @@ void os::Bsd::check_signal_handler(int sig) { jvmHandler = (address)user_handler(); break; - case INTERRUPT_SIGNAL: - jvmHandler = CAST_FROM_FN_PTR(address, SIG_DFL); - break; - default: if (sig == SR_signum) { jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler); @@ -3745,7 +3751,7 @@ bool os::find(address addr, outputStream* st) { // able to use structured exception handling (thread-local exception filters) // on, e.g., Win32. void os::os_exception_wrapper(java_call_t f, JavaValue* value, - methodHandle* method, JavaCallArguments* args, + const methodHandle& method, JavaCallArguments* args, Thread* thread) { f(value, method, args, thread); } @@ -3901,9 +3907,6 @@ int os::available(int fd, jlong *bytes) { if (::fstat(fd, &buf) >= 0) { mode = buf.st_mode; if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { - // XXX: is the following call interruptible? If so, this might - // need to go through the INTERRUPT_IO() wrapper as for other - // blocking, interruptible calls in this file. int n; if (::ioctl(fd, FIONREAD, &n) >= 0) { *bytes = n; diff --git a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp index 4764e0616eb..b4c7328914c 100644 --- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp +++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp @@ -217,9 +217,9 @@ static bool is_statbuf_secure(struct stat *statp) { // return false; } - // See if the uid of the directory matches the effective uid of the process. - // - if (statp->st_uid != geteuid()) { + // If user is not root then see if the uid of the directory matches the effective uid of the process. + uid_t euid = geteuid(); + if ((euid != 0) && (statp->st_uid != euid)) { // The directory was not created by this user, declare it insecure. // return false; diff --git a/hotspot/src/os/linux/vm/attachListener_linux.cpp b/hotspot/src/os/linux/vm/attachListener_linux.cpp index 1c71716c78f..4e54d898fb2 100644 --- a/hotspot/src/os/linux/vm/attachListener_linux.cpp +++ b/hotspot/src/os/linux/vm/attachListener_linux.cpp @@ -254,6 +254,8 @@ LinuxAttachOperation* LinuxAttachListener::read_request(int s) { do { int n; RESTARTABLE(read(s, buf+off, left), n); + assert(n <= left, "buffer was too small, impossible!"); + buf[max_len - 1] = '\0'; if (n == -1) { return NULL; // reset by peer or other error } diff --git a/hotspot/src/os/linux/vm/jvm_linux.cpp b/hotspot/src/os/linux/vm/jvm_linux.cpp index ba84788a1b7..35404b8217a 100644 --- a/hotspot/src/os/linux/vm/jvm_linux.cpp +++ b/hotspot/src/os/linux/vm/jvm_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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,7 +47,6 @@ JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler)) : handler; switch (sig) { /* The following are already used by the VM. */ - case INTERRUPT_SIGNAL: case SIGFPE: case SIGILL: case SIGSEGV: diff --git a/hotspot/src/os/linux/vm/jvm_linux.h b/hotspot/src/os/linux/vm/jvm_linux.h index dd5e3894186..950319be265 100644 --- a/hotspot/src/os/linux/vm/jvm_linux.h +++ b/hotspot/src/os/linux/vm/jvm_linux.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -88,7 +88,6 @@ /* Signal definitions */ #define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */ -#define INTERRUPT_SIGNAL SIGUSR1 /* Interruptible I/O support. */ #define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */ #define SHUTDOWN2_SIGNAL SIGINT #define SHUTDOWN3_SIGNAL SIGTERM diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 05d1850d52e..8c5486f5d19 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2302,7 +2302,6 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { print_signal_handler(st, SIGPIPE, buf, buflen); print_signal_handler(st, SIGXFSZ, buf, buflen); print_signal_handler(st, SIGILL , buf, buflen); - print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen); print_signal_handler(st, SR_signum, buf, buflen); print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen); print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); @@ -2794,7 +2793,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, int os::Linux::sched_getcpu_syscall(void) { - unsigned int cpu; + unsigned int cpu = 0; int retval = -1; #if defined(IA32) @@ -2820,7 +2819,6 @@ int os::Linux::sched_getcpu_syscall(void) { // Something to do with the numa-aware allocator needs these symbols extern "C" JNIEXPORT void numa_warn(int number, char *where, ...) { } extern "C" JNIEXPORT void numa_error(char *where) { } -extern "C" JNIEXPORT int fork1() { return fork(); } // If we are running with libnuma version > 2, then we should @@ -4187,8 +4185,8 @@ static bool call_chained_handler(struct sigaction *actp, int sig, sigaddset(&(actp->sa_mask), sig); } - sa_handler_t hand; - sa_sigaction_t sa; + sa_handler_t hand = NULL; + sa_sigaction_t sa = NULL; bool siginfo_flag_set = (actp->sa_flags & SA_SIGINFO) != 0; // retrieve the chained handler if (siginfo_flag_set) { @@ -4254,7 +4252,9 @@ int os::Linux::get_our_sigflags(int sig) { void os::Linux::set_our_sigflags(int sig, int flags) { assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); - sigflags[sig] = flags; + if (sig > 0 && sig < MAXSIGNUM) { + sigflags[sig] = flags; + } } void os::Linux::set_signal_handler(int sig, bool set_installed) { @@ -4393,7 +4393,7 @@ jlong os::Linux::fast_thread_cpu_time(clockid_t clockid) { static const char* get_signal_handler_name(address handler, char* buf, int buflen) { - int offset; + int offset = 0; bool found = os::dll_address_to_library_name(handler, buf, buflen, &offset); if (found) { // skip directory names @@ -4496,7 +4496,6 @@ void os::run_periodic_checks() { } DO_SIGNAL_CHECK(SR_signum); - DO_SIGNAL_CHECK(INTERRUPT_SIGNAL); } typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *); @@ -4542,10 +4541,6 @@ void os::Linux::check_signal_handler(int sig) { jvmHandler = (address)user_handler(); break; - case INTERRUPT_SIGNAL: - jvmHandler = CAST_FROM_FN_PTR(address, SIG_DFL); - break; - default: if (sig == SR_signum) { jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler); @@ -4960,7 +4955,7 @@ bool os::find(address addr, outputStream* st) { // able to use structured exception handling (thread-local exception filters) // on, e.g., Win32. void -os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, +os::os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& method, JavaCallArguments* args, Thread* thread) { f(value, method, args, thread); } @@ -5130,9 +5125,6 @@ int os::available(int fd, jlong *bytes) { if (::fstat64(fd, &buf64) >= 0) { mode = buf64.st_mode; if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { - // XXX: is the following call interruptible? If so, this might - // need to go through the INTERRUPT_IO() wrapper as for other - // blocking, interruptible calls in this file. int n; if (::ioctl(fd, FIONREAD, &n) >= 0) { *bytes = n; @@ -5937,22 +5929,20 @@ int os::get_core_path(char* buffer, size_t bufferSize) { char core_pattern[core_pattern_len] = {0}; int core_pattern_file = ::open("/proc/sys/kernel/core_pattern", O_RDONLY); - if (core_pattern_file != -1) { - ssize_t ret = ::read(core_pattern_file, core_pattern, core_pattern_len); - ::close(core_pattern_file); - - if (ret > 0) { - char *last_char = core_pattern + strlen(core_pattern) - 1; - - if (*last_char == '\n') { - *last_char = '\0'; - } - } + if (core_pattern_file == -1) { + return -1; } - if (strlen(core_pattern) == 0) { + ssize_t ret = ::read(core_pattern_file, core_pattern, core_pattern_len); + ::close(core_pattern_file); + if (ret <= 0 || ret >= core_pattern_len || core_pattern[0] == '\n') { return -1; } + if (core_pattern[ret-1] == '\n') { + core_pattern[ret-1] = '\0'; + } else { + core_pattern[ret] = '\0'; + } char *pid_pos = strstr(core_pattern, "%p"); int written; diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index e30554cb10d..47ad1217d1e 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -177,6 +177,10 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment) { return aligned_base; } +int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { + return vsnprintf(buf, len, fmt, args); +} + void os::Posix::print_load_average(outputStream* st) { st->print("load average:"); double loadavg[3]; diff --git a/hotspot/src/os/solaris/dtrace/libjvm_db.c b/hotspot/src/os/solaris/dtrace/libjvm_db.c index 6bad77b68bb..e00284532a6 100644 --- a/hotspot/src/os/solaris/dtrace/libjvm_db.c +++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c @@ -834,7 +834,7 @@ line_number_from_bci(jvm_agent_t* J, Vframe_t *vf) if (stream_bci == vf->bci) { /* perfect match */ if (debug > 2) - fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line); + fprintf(stderr, "\t line_number_from_bci: END: exact line: %d \n\n", vf->line); vf->line = stream_line; return PS_OK; } else { @@ -843,14 +843,14 @@ line_number_from_bci(jvm_agent_t* J, Vframe_t *vf) best_bci = stream_bci; vf->line = stream_line; if (debug > 2) { - fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n", + fprintf(stderr, "\t line_number_from_bci: best_bci: %d, best_line: %d\n", best_bci, vf->line); } } } } if (debug > 2) - fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line); + fprintf(stderr, "\t line_number_from_bci: END: line: %d \n\n", vf->line); return PS_OK; fail: @@ -1002,7 +1002,7 @@ static int scopeDesc_chain(Nmethod_t *N) { err = line_number_from_bci(N->J, vf); CHECK_FAIL(err); if (debug > 2) { - fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n", + fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %d\n", vf->method, vf->line); } } @@ -1338,7 +1338,7 @@ int Jget_vframe(jvm_agent_t* J, int vframe_no, jframe->bci = vf->bci; jframe->line = vf->line; if (debug) { - fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n", + fprintf(stderr, "\t Jget_vframe: method name: %s, line: %d\n", name, vf->line); } return PS_OK; diff --git a/hotspot/src/os/solaris/vm/jvm_solaris.cpp b/hotspot/src/os/solaris/vm/jvm_solaris.cpp index 2f5ccb3bb17..ae2eb037dc8 100644 --- a/hotspot/src/os/solaris/vm/jvm_solaris.cpp +++ b/hotspot/src/os/solaris/vm/jvm_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -73,11 +73,6 @@ JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler)) if (os::Solaris::is_sig_ignored(sig)) return (void*)1; } - /* Check parameterized signals. Don't allow sharing of our interrupt signal */ - if (sig == os::Solaris::SIGinterrupt()) { - return (void *)-1; - } - void* oldHandler = os::signal(sig, newHandler); if (oldHandler == os::user_handler()) { return (void *)2; diff --git a/hotspot/src/os/solaris/vm/jvm_solaris.h b/hotspot/src/os/solaris/vm/jvm_solaris.h index f1fa075bc88..5e4c41e7680 100644 --- a/hotspot/src/os/solaris/vm/jvm_solaris.h +++ b/hotspot/src/os/solaris/vm/jvm_solaris.h @@ -87,7 +87,6 @@ /* Signal definitions */ #define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */ -#define INTERRUPT_SIGNAL SIGUSR1 /* Interruptible I/O support. */ #define ASYNC_SIGNAL SIGUSR2 /* Watcher & async err support. */ #define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */ #define SHUTDOWN2_SIGNAL SIGINT @@ -95,8 +94,7 @@ /* alternative signals used with -XX:+UseAltSigs (or for backward compatibility with 1.2, -Xusealtsigs) flag. Chosen to be unlikely to conflict with applications embedding the vm */ -#define ALT_INTERRUPT_SIGNAL (SIGRTMIN + SIGRTMAX)/2 /* alternate intio signal */ -#define ALT_ASYNC_SIGNAL ALT_INTERRUPT_SIGNAL+1 /* alternate async signal */ +#define ALT_ASYNC_SIGNAL (SIGRTMIN + SIGRTMAX)/2 /* alternate async signal */ /* With 1.4.1 libjsig added versioning: used in os_solaris.cpp and jsig.c */ #define JSIG_VERSION_1_4_1 0x30140100 diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 2f5172da6b8..36ee014bed3 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -138,11 +138,6 @@ #define LGRP_RSRC_MEM 1 /* memory resources */ #endif -// see thr_setprio(3T) for the basis of these numbers -#define MinimumPriority 0 -#define NormalPriority 64 -#define MaximumPriority 127 - // Values for ThreadPriorityPolicy == 1 int prio_policy1[CriticalPriority+1] = { -99999, 0, 16, 32, 48, 64, @@ -1003,8 +998,9 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, // defined for >= Solaris 10. This allows builds on earlier versions // of Solaris to take advantage of the newly reserved Solaris JVM signals -// With SIGJVM1, SIGJVM2, INTERRUPT_SIGNAL is SIGJVM1, ASYNC_SIGNAL is SIGJVM2 -// and -XX:+UseAltSigs does nothing since these should have no conflict +// With SIGJVM1, SIGJVM2, ASYNC_SIGNAL is SIGJVM2 and -XX:+UseAltSigs does +// nothing since these should have no conflict. Previously INTERRUPT_SIGNAL +// was SIGJVM1. // #if !defined(SIGJVM1) #define SIGJVM1 39 @@ -1013,7 +1009,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, debug_only(static bool signal_sets_initialized = false); static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs; -int os::Solaris::_SIGinterrupt = INTERRUPT_SIGNAL; + int os::Solaris::_SIGasync = ASYNC_SIGNAL; bool os::Solaris::is_sig_ignored(int sig) { @@ -1058,17 +1054,13 @@ void os::Solaris::signal_sets_init() { sigaddset(&unblocked_sigs, SIGFPE); if (isJVM1available) { - os::Solaris::set_SIGinterrupt(SIGJVM1); os::Solaris::set_SIGasync(SIGJVM2); } else if (UseAltSigs) { - os::Solaris::set_SIGinterrupt(ALT_INTERRUPT_SIGNAL); os::Solaris::set_SIGasync(ALT_ASYNC_SIGNAL); } else { - os::Solaris::set_SIGinterrupt(INTERRUPT_SIGNAL); os::Solaris::set_SIGasync(ASYNC_SIGNAL); } - sigaddset(&unblocked_sigs, os::Solaris::SIGinterrupt()); sigaddset(&unblocked_sigs, os::Solaris::SIGasync()); if (!ReduceSignalUsage) { @@ -1939,8 +1931,6 @@ void os::print_siginfo(outputStream* st, void* siginfo) { static int Maxsignum = 0; static int *ourSigFlags = NULL; -extern "C" void sigINTRHandler(int, siginfo_t*, void*); - int os::Solaris::get_our_sigflags(int sig) { assert(ourSigFlags!=NULL, "signal data structure not initialized"); assert(sig > 0 && sig < Maxsignum, "vm signal out of expected range"); @@ -2005,8 +1995,7 @@ static void print_signal_handler(outputStream* st, int sig, os::Posix::print_sa_flags(st, sa.sa_flags); // Check: is it our handler? - if (handler == CAST_FROM_FN_PTR(address, signalHandler) || - handler == CAST_FROM_FN_PTR(address, sigINTRHandler)) { + if (handler == CAST_FROM_FN_PTR(address, signalHandler)) { // It is our signal handler // check for flags if (sa.sa_flags != os::Solaris::get_our_sigflags(sig)) { @@ -2026,13 +2015,11 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { print_signal_handler(st, SIGPIPE, buf, buflen); print_signal_handler(st, SIGXFSZ, buf, buflen); print_signal_handler(st, SIGILL , buf, buflen); - print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen); print_signal_handler(st, ASYNC_SIGNAL, buf, buflen); print_signal_handler(st, BREAK_SIGNAL, buf, buflen); print_signal_handler(st, SHUTDOWN1_SIGNAL , buf, buflen); print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); print_signal_handler(st, SHUTDOWN3_SIGNAL, buf, buflen); - print_signal_handler(st, os::Solaris::SIGinterrupt(), buf, buflen); print_signal_handler(st, os::Solaris::SIGasync(), buf, buflen); } @@ -3146,7 +3133,7 @@ static int myMax = 0; static int myCur = 0; static bool priocntl_enable = false; -static const int criticalPrio = 60; // FX/60 is critical thread class/priority on T4 +static const int criticalPrio = FXCriticalPriority; static int java_MaxPriority_to_os_priority = 0; // Saved mapping @@ -3774,7 +3761,7 @@ ExtendedPC os::get_thread_pc(Thread* thread) { // This does not do anything on Solaris. This is basically a hook for being // able to use structured exception handling (thread-local exception filters) on, e.g., Win32. void os::os_exception_wrapper(java_call_t f, JavaValue* value, - methodHandle* method, JavaCallArguments* args, + const methodHandle& method, JavaCallArguments* args, Thread* thread) { f(value, method, args, thread); } @@ -3796,7 +3783,6 @@ void os::os_exception_wrapper(java_call_t f, JavaValue* value, // SIGBUS, SIGSEGV, SIGILL, SIGFPE, BREAK_SIGNAL, SIGPIPE, SIGXFSZ, // os::Solaris::SIGasync // It should be consulted by handlers for any of those signals. -// It explicitly does not recognize os::Solaris::SIGinterrupt // // The caller of this routine must pass in the three arguments supplied // to the function referred to in the "sa_sigaction" (not the "sa_handler") @@ -3818,20 +3804,6 @@ void signalHandler(int sig, siginfo_t* info, void* ucVoid) { errno = orig_errno; } -// Do not delete - if guarantee is ever removed, a signal handler (even empty) -// is needed to provoke threads blocked on IO to return an EINTR -// Note: this explicitly does NOT call JVM_handle_solaris_signal and -// does NOT participate in signal chaining due to requirement for -// NOT setting SA_RESTART to make EINTR work. -extern "C" void sigINTRHandler(int sig, siginfo_t* info, void* ucVoid) { - if (UseSignalChaining) { - struct sigaction *actp = os::Solaris::get_chained_signal_action(sig); - if (actp && actp->sa_handler) { - vm_exit_during_initialization("Signal chaining detected for VM interrupt signal, try -XX:+UseAltSigs"); - } - } -} - // This boolean allows users to forward their own non-matching signals // to JVM_handle_solaris_signal, harmlessly. bool os::Solaris::signal_handlers_are_installed = false; @@ -3969,13 +3941,6 @@ void os::Solaris::set_signal_handler(int sig, bool set_installed, // not using stack banging if (!UseStackBanging && sig == SIGSEGV) { sigAct.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; - } else if (sig == os::Solaris::SIGinterrupt()) { - // Interruptible i/o requires SA_RESTART cleared so EINTR - // is returned instead of restarting system calls - sigemptyset(&sigAct.sa_mask); - sigAct.sa_handler = NULL; - sigAct.sa_flags = SA_SIGINFO; - sigAct.sa_sigaction = sigINTRHandler; } else { sigAct.sa_flags = SA_SIGINFO | SA_RESTART; } @@ -4027,7 +3992,6 @@ void os::run_periodic_checks() { } // See comments above for using JVM1/JVM2 and UseAltSigs - DO_SIGNAL_CHECK(os::Solaris::SIGinterrupt()); DO_SIGNAL_CHECK(os::Solaris::SIGasync()); } @@ -4072,12 +4036,9 @@ void os::Solaris::check_signal_handler(int sig) { break; default: - int intrsig = os::Solaris::SIGinterrupt(); int asynsig = os::Solaris::SIGasync(); - if (sig == intrsig) { - jvmHandler = CAST_FROM_FN_PTR(address, sigINTRHandler); - } else if (sig == asynsig) { + if (sig == asynsig) { jvmHandler = CAST_FROM_FN_PTR(address, signalHandler); } else { return; @@ -4148,8 +4109,7 @@ void os::Solaris::install_signal_handlers() { set_signal_handler(SIGFPE, true, true); - if (os::Solaris::SIGinterrupt() > OLDMAXSIGNUM || os::Solaris::SIGasync() > OLDMAXSIGNUM) { - + if (os::Solaris::SIGasync() > OLDMAXSIGNUM) { // Pre-1.4.1 Libjsig limited to signal chaining signals <= 32 so // can not register overridable signals which might be > 32 if (libjsig_is_loaded && libjsigversion <= JSIG_VERSION_1_4_1) { @@ -4159,8 +4119,6 @@ void os::Solaris::install_signal_handlers() { } } - // Never ok to chain our SIGinterrupt - set_signal_handler(os::Solaris::SIGinterrupt(), true, false); set_signal_handler(os::Solaris::SIGasync(), true, true); if (libjsig_is_loaded && !libjsigdone) { diff --git a/hotspot/src/os/solaris/vm/os_solaris.hpp b/hotspot/src/os/solaris/vm/os_solaris.hpp index 859b9ae2ca6..0f9b86d9ca8 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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,14 @@ // Solaris_OS defines the interface to Solaris operating systems +// see thr_setprio(3T) for the basis of these numbers +#define MinimumPriority 0 +#define NormalPriority 64 +#define MaximumPriority 127 + +// FX/60 is critical thread class/priority on T4 +#define FXCriticalPriority 60 + // Information about the protection of the page at address '0' on this os. static bool zero_page_read_protected() { return true; } @@ -114,16 +122,13 @@ class Solaris { static void save_preinstalled_handler(int, struct sigaction&); static void check_signal_handler(int sig); // For overridable signals - static int _SIGinterrupt; // user-overridable INTERRUPT_SIGNAL static int _SIGasync; // user-overridable ASYNC_SIGNAL - static void set_SIGinterrupt(int newsig) { _SIGinterrupt = newsig; } static void set_SIGasync(int newsig) { _SIGasync = newsig; } public: // Large Page Support--ISM. static bool largepage_range(char* addr, size_t size); - static int SIGinterrupt() { return _SIGinterrupt; } static int SIGasync() { return _SIGasync; } static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp index 3456414f048..4ececaf1ceb 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp @@ -65,6 +65,8 @@ inline void os::bang_stack_shadow_pages() { } inline void os::dll_unload(void *lib) { ::dlclose(lib); } +inline const int os::default_file_open_flags() { return 0;} + inline DIR* os::opendir(const char* dirname) { assert(dirname != NULL, "just checking"); return ::opendir(dirname); diff --git a/hotspot/src/os/windows/vm/attachListener_windows.cpp b/hotspot/src/os/windows/vm/attachListener_windows.cpp index 916118eb9fa..4550cd1eb1c 100644 --- a/hotspot/src/os/windows/vm/attachListener_windows.cpp +++ b/hotspot/src/os/windows/vm/attachListener_windows.cpp @@ -191,7 +191,8 @@ int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, // check that all paramteres to the operation if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG; if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; - if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; + if (strlen(arg1) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; + if (strlen(arg2) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG; if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG; // check for a well-formed pipename diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 697b5bebdaf..45a9bb11d0b 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1608,6 +1608,15 @@ void os::get_summary_os_info(char* buf, size_t buflen) { if (nl != NULL) *nl = '\0'; } +int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { + int ret = vsnprintf(buf, len, fmt, args); + // Get the correct buffer size if buf is too small + if (ret < 0) { + return _vscprintf(fmt, args); + } + return ret; +} + void os::print_os_info_brief(outputStream* st) { os::print_os_info(st); } diff --git a/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp b/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp index 175019b8644..c35f85524ca 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp @@ -30,7 +30,7 @@ static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { (void)memmove(to, from, count * HeapWordSize); #else // Includes a zero-count check. - intx temp; + intx temp = 0; __asm__ volatile(" testl %6,%6 ;" " jz 7f ;" " cmpl %4,%5 ;" @@ -88,7 +88,7 @@ static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { } #else // Includes a zero-count check. - intx temp; + intx temp = 0; __asm__ volatile(" testl %6,%6 ;" " jz 3f ;" " cmpl $32,%6 ;" @@ -145,7 +145,7 @@ static void pd_conjoint_bytes(void* from, void* to, size_t count) { (void)memmove(to, from, count); #else // Includes a zero-count check. - intx temp; + intx temp = 0; __asm__ volatile(" testl %6,%6 ;" " jz 13f ;" " cmpl %4,%5 ;" diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index ab54a71185b..d139566c72d 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -325,8 +325,6 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, } } - guarantee(sig != os::Solaris::SIGinterrupt(), "Can not chain VM interrupt signal, try -XX:+UseAltSigs"); - if (sig == os::Solaris::SIGasync()) { if (thread || vmthread) { OSThread::SR_handler(t, uc); diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index fdc17b596ad..28845c326b8 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -382,8 +382,6 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, } } - guarantee(sig != os::Solaris::SIGinterrupt(), "Can not chain VM interrupt signal, try -XX:+UseAltSigs"); - if (sig == os::Solaris::SIGasync()) { if(thread || vmthread){ OSThread::SR_handler(t, uc); diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index d63732be380..f17330ace65 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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,7 +71,7 @@ extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* ); // Install a win32 structured exception handler around thread. -void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) { +void os::os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& method, JavaCallArguments* args, Thread* thread) { __try { #ifndef AMD64 diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index 79a65f16833..82ba5f9e2d7 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -607,6 +607,8 @@ bool InstructForm::needs_anti_dependence_check(FormDict &globals) const { ( strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || strcmp(_matrule->_rChild->_opType,"StrIndexOf" )==0 || + strcmp(_matrule->_rChild->_opType,"StrIndexOfChar" )==0 || + strcmp(_matrule->_rChild->_opType,"HasNegatives" )==0 || strcmp(_matrule->_rChild->_opType,"AryEq" )==0 )) return true; @@ -887,11 +889,16 @@ uint InstructForm::oper_input_base(FormDict &globals) { ( strcmp(_matrule->_rChild->_opType,"AryEq" )==0 || strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || + strcmp(_matrule->_rChild->_opType,"StrInflatedCopy" )==0 || + strcmp(_matrule->_rChild->_opType,"StrCompressedCopy" )==0 || strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 || + strcmp(_matrule->_rChild->_opType,"StrIndexOfChar")==0 || + strcmp(_matrule->_rChild->_opType,"HasNegatives")==0 || strcmp(_matrule->_rChild->_opType,"EncodeISOArray")==0)) { // String.(compareTo/equals/indexOf) and Arrays.equals // and sun.nio.cs.iso8859_1$Encoder.EncodeISOArray // take 1 control and 1 memory edges. + // Also String.(compressedCopy/inflatedCopy). return 2; } diff --git a/hotspot/src/share/vm/adlc/main.cpp b/hotspot/src/share/vm/adlc/main.cpp index ef0a71fef25..7453d38d61b 100644 --- a/hotspot/src/share/vm/adlc/main.cpp +++ b/hotspot/src/share/vm/adlc/main.cpp @@ -221,6 +221,7 @@ int main(int argc, char *argv[]) AD.addInclude(AD._CPP_file, "oops/method.hpp"); AD.addInclude(AD._CPP_file, "oops/oop.inline.hpp"); AD.addInclude(AD._CPP_file, "opto/cfgnode.hpp"); + AD.addInclude(AD._CPP_file, "opto/intrinsicnode.hpp"); AD.addInclude(AD._CPP_file, "opto/locknode.hpp"); AD.addInclude(AD._CPP_file, "opto/opcodes.hpp"); AD.addInclude(AD._CPP_file, "opto/regalloc.hpp"); @@ -256,6 +257,7 @@ int main(int argc, char *argv[]) AD.addInclude(AD._DFA_file, "precompiled.hpp"); AD.addInclude(AD._DFA_file, "adfiles", get_basename(AD._HPP_file._name)); AD.addInclude(AD._DFA_file, "opto/cfgnode.hpp"); // Use PROB_MAX in predicate. + AD.addInclude(AD._DFA_file, "opto/intrinsicnode.hpp"); AD.addInclude(AD._DFA_file, "opto/matcher.hpp"); AD.addInclude(AD._DFA_file, "opto/opcodes.hpp"); AD.addInclude(AD._DFA_file, "opto/convertnode.hpp"); diff --git a/hotspot/src/share/vm/asm/codeBuffer.cpp b/hotspot/src/share/vm/asm/codeBuffer.cpp index 1ab5a5d6d8d..4ffcf0c81a2 100644 --- a/hotspot/src/share/vm/asm/codeBuffer.cpp +++ b/hotspot/src/share/vm/asm/codeBuffer.cpp @@ -509,7 +509,7 @@ static void append_oop_references(GrowableArray* oops, Klass* k) { } } -void CodeBuffer::finalize_oop_references(methodHandle mh) { +void CodeBuffer::finalize_oop_references(const methodHandle& mh) { No_Safepoint_Verifier nsv; GrowableArray oops; @@ -873,6 +873,7 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) { // Figure new capacity for each section. csize_t new_capacity[SECT_LIMIT]; + memset(new_capacity, 0, sizeof(csize_t) * SECT_LIMIT); csize_t new_total_cap = figure_expanded_capacities(which_cs, amount, new_capacity); diff --git a/hotspot/src/share/vm/asm/codeBuffer.hpp b/hotspot/src/share/vm/asm/codeBuffer.hpp index 50b699c5e3e..387a5b7cced 100644 --- a/hotspot/src/share/vm/asm/codeBuffer.hpp +++ b/hotspot/src/share/vm/asm/codeBuffer.hpp @@ -541,7 +541,7 @@ class CodeBuffer: public StackObj { bool insts_contains2(address pc) const { return _insts.contains2(pc); } // Record any extra oops required to keep embedded metadata alive - void finalize_oop_references(methodHandle method); + void finalize_oop_references(const methodHandle& method); // Allocated size in all sections, when aligned and concatenated // (this is the eventual state of the content in its final diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp index 26cee689ab0..e4976f18bc6 100644 --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp @@ -639,7 +639,7 @@ void Canonicalizer::do_If(If* x) { if (l == r && !lt->is_float_kind()) { // pattern: If (a cond a) => simplify to Goto - BlockBegin* sux; + BlockBegin* sux = NULL; switch (x->cond()) { case If::eql: sux = x->sux_for(true); break; case If::neq: sux = x->sux_for(false); break; @@ -647,6 +647,7 @@ void Canonicalizer::do_If(If* x) { case If::leq: sux = x->sux_for(true); break; case If::gtr: sux = x->sux_for(false); break; case If::geq: sux = x->sux_for(true); break; + default: ShouldNotReachHere(); } // If is a safepoint then the debug information should come from the state_before of the If. set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); @@ -684,7 +685,7 @@ void Canonicalizer::do_If(If* x) { } else { // two successors differ and two successors are the same => simplify to: If (x cmp y) // determine new condition & successors - If::Condition cond; + If::Condition cond = If::eql; BlockBegin* tsux = NULL; BlockBegin* fsux = NULL; if (lss_sux == eql_sux) { cond = If::leq; tsux = lss_sux; fsux = gtr_sux; } @@ -727,7 +728,9 @@ void Canonicalizer::do_If(If* x) { set_canonical(new IfInstanceOf(inst->klass(), inst->obj(), true, inst->state_before()->bci(), is_inst_sux, no_inst_sux)); } } - } else if (rt == objectNull && (l->as_NewInstance() || l->as_NewArray())) { + } else if (rt == objectNull && + (l->as_NewInstance() || l->as_NewArray() || + (UseNewCode && l->as_Local() && l->as_Local()->is_receiver()))) { if (x->cond() == Instruction::eql) { BlockBegin* sux = x->fsux(); set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp index 8377dbcb56c..5dbe6c209f3 100644 --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -98,7 +98,7 @@ BufferBlob* Compiler::init_buffer_blob() { return buffer_blob; } -bool Compiler::is_intrinsic_supported(methodHandle method) { +bool Compiler::is_intrinsic_supported(const methodHandle& method) { vmIntrinsics::ID id = method->intrinsic_id(); assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); @@ -225,6 +225,8 @@ bool Compiler::is_intrinsic_supported(methodHandle method) { case vmIntrinsics::_updateByteBufferCRC32: case vmIntrinsics::_compareAndSwapInt: case vmIntrinsics::_compareAndSwapObject: + case vmIntrinsics::_getCharStringU: + case vmIntrinsics::_putCharStringU: #ifdef TRACE_HAVE_INTRINSICS case vmIntrinsics::_classID: case vmIntrinsics::_threadID: diff --git a/hotspot/src/share/vm/c1/c1_Compiler.hpp b/hotspot/src/share/vm/c1/c1_Compiler.hpp index 5ac2ade31fc..fb3f1877eb6 100644 --- a/hotspot/src/share/vm/c1/c1_Compiler.hpp +++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -57,7 +57,7 @@ class Compiler: public AbstractCompiler { virtual void print_timers(); // Check if the C1 compiler supports an intrinsic for 'method'. - virtual bool is_intrinsic_supported(methodHandle method); + virtual bool is_intrinsic_supported(const methodHandle& method); // Size of the code buffer static int code_buffer_size(); diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 5b27aae2a05..6513fe1ab33 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -3089,7 +3089,7 @@ ValueStack* GraphBuilder::state_at_entry() { int idx = 0; if (!method()->is_static()) { // we should always see the receiver - state->store_local(idx, new Local(method()->holder(), objectType, idx)); + state->store_local(idx, new Local(method()->holder(), objectType, idx, true)); idx = 1; } @@ -3101,7 +3101,7 @@ ValueStack* GraphBuilder::state_at_entry() { // don't allow T_ARRAY to propagate into locals types if (basic_type == T_ARRAY) basic_type = T_OBJECT; ValueType* vt = as_ValueType(basic_type); - state->store_local(idx, new Local(type, vt, idx)); + state->store_local(idx, new Local(type, vt, idx, false)); idx += type->size(); } @@ -3445,6 +3445,8 @@ void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) { case vmIntrinsics::_getAndSetInt : case vmIntrinsics::_getAndSetLong : case vmIntrinsics::_getAndSetObject : append_unsafe_get_and_set_obj(callee, false); return; + case vmIntrinsics::_getCharStringU : append_char_access(callee, false); return; + case vmIntrinsics::_putCharStringU : append_char_access(callee, true); return; default: break; } @@ -3823,8 +3825,8 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode caller_state->truncate_stack(args_base); assert(callee_state->stack_size() == 0, "callee stack must be empty"); - Value lock; - BlockBegin* sync_handler; + Value lock = NULL; + BlockBegin* sync_handler = NULL; // Inline the locking of the receiver if the callee is synchronized if (callee->is_synchronized()) { @@ -4179,6 +4181,30 @@ void GraphBuilder::append_unsafe_CAS(ciMethod* callee) { compilation()->set_has_unsafe_access(true); } +void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) { + // This intrinsic accesses byte[] array as char[] array. Computing the offsets + // correctly requires matched array shapes. + assert (arrayOopDesc::base_offset_in_bytes(T_CHAR) == arrayOopDesc::base_offset_in_bytes(T_BYTE), + "sanity: byte[] and char[] bases agree"); + assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2, + "sanity: byte[] and char[] scales agree"); + + ValueStack* state_before = copy_state_indexed_access(); + compilation()->set_has_access_indexed(true); + Values* args = state()->pop_arguments(callee->arg_size()); + Value array = args->at(0); + Value index = args->at(1); + if (is_store) { + Value value = args->at(2); + Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before)); + store->set_flag(Instruction::NeedsRangeCheckFlag, false); + _memory->store_value(value); + } else { + Instruction* load = append(new LoadIndexed(array, index, NULL, T_CHAR, state_before)); + load->set_flag(Instruction::NeedsRangeCheckFlag, false); + push(load->type(), load); + } +} void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) { CompileLog* log = compilation()->log(); diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp index 40af90bc13d..4fb1e184d6d 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp @@ -372,6 +372,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { void append_unsafe_put_raw(ciMethod* callee, BasicType t); void append_unsafe_CAS(ciMethod* callee); void append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add); + void append_char_access(ciMethod* callee, bool is_store); void print_inlining(ciMethod* callee, const char* msg = NULL, bool success = true); diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp index b61786c58c5..8f6bf233f3d 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp @@ -701,19 +701,22 @@ LEAF(Phi, Instruction) LEAF(Local, Instruction) private: int _java_index; // the local index within the method to which the local belongs + bool _is_receiver; // if local variable holds the receiver: "this" for non-static methods ciType* _declared_type; public: // creation - Local(ciType* declared, ValueType* type, int index) + Local(ciType* declared, ValueType* type, int index, bool receiver) : Instruction(type) , _java_index(index) , _declared_type(declared) + , _is_receiver(receiver) { NOT_PRODUCT(set_printable_bci(-1)); } // accessors int java_index() const { return _java_index; } + bool is_receiver() const { return _is_receiver; } virtual ciType* declared_type() const { return _declared_type; } diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index d5a3f947b59..e8bc40eba93 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -161,8 +161,6 @@ class LIR_Assembler: public CompilationResourceObj { // particular sparc uses this for delay slot filling. void peephole(LIR_List* list); - void emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst, CodeEmitInfo* info); - void return_op(LIR_Opr result); // returns offset of poll instruction diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index f188dfb942d..a45d221f740 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -3348,7 +3348,7 @@ void LIRGenerator::do_ProfileInvoke(ProfileInvoke* x) { } void LIRGenerator::increment_event_counter(CodeEmitInfo* info, int bci, bool backedge) { - int freq_log; + int freq_log = 0; int level = compilation()->env()->comp_level(); if (level == CompLevel_limited_profile) { freq_log = (backedge ? Tier2BackedgeNotifyFreqLog : Tier2InvokeNotifyFreqLog); @@ -3394,7 +3394,7 @@ void LIRGenerator::increment_event_counter_impl(CodeEmitInfo* info, assert(level > CompLevel_simple, "Shouldn't be here"); int offset = -1; - LIR_Opr counter_holder; + LIR_Opr counter_holder = NULL; if (level == CompLevel_limited_profile) { MethodCounters* counters_adr = method->ensure_method_counters(); if (counters_adr == NULL) { diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index f0f7d3463a8..69956e7d9e0 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -414,7 +414,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { } static LIR_Condition lir_cond(If::Condition cond) { - LIR_Condition l; + LIR_Condition l = lir_cond_unknown; switch (cond) { case If::eql: l = lir_cond_equal; break; case If::neq: l = lir_cond_notEqual; break; @@ -424,6 +424,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { case If::gtr: l = lir_cond_greater; break; case If::aeq: l = lir_cond_aboveEqual; break; case If::beq: l = lir_cond_belowEqual; break; + default: fatal("You must pass valid If::Condition"); }; return l; } diff --git a/hotspot/src/share/vm/ci/ciArrayKlass.cpp b/hotspot/src/share/vm/ci/ciArrayKlass.cpp index 7d2d19774c0..ebff3a90d90 100644 --- a/hotspot/src/share/vm/ci/ciArrayKlass.cpp +++ b/hotspot/src/share/vm/ci/ciArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ // // Loaded array klass. ciArrayKlass::ciArrayKlass(KlassHandle h_k) : ciKlass(h_k) { - assert(get_Klass()->oop_is_array(), "wrong type"); + assert(get_Klass()->is_array_klass(), "wrong type"); _dimension = get_ArrayKlass()->dimension(); } diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 4e1d2e99bd1..9c9d7b300c2 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -366,11 +366,11 @@ bool ciEnv::check_klass_accessibility(ciKlass* accessing_klass, return true; } - if (resolved_klass->oop_is_objArray()) { + if (resolved_klass->is_objArray_klass()) { // Find the element klass, if this is an array. resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass(); } - if (resolved_klass->oop_is_instance()) { + if (resolved_klass->is_instance_klass()) { return Reflection::verify_class_access(accessing_klass->get_Klass(), resolved_klass, true); @@ -381,7 +381,7 @@ bool ciEnv::check_klass_accessibility(ciKlass* accessing_klass, // ------------------------------------------------------------------ // ciEnv::get_klass_by_name_impl ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, - constantPoolHandle cpool, + const constantPoolHandle& cpool, ciSymbol* name, bool require_local) { ASSERT_IN_VM; @@ -503,7 +503,7 @@ ciKlass* ciEnv::get_klass_by_name(ciKlass* accessing_klass, // ciEnv::get_klass_by_index_impl // // Implementation of get_klass_by_index. -ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool, +ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, int index, bool& is_accessible, ciInstanceKlass* accessor) { @@ -560,7 +560,7 @@ ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool, // ciEnv::get_klass_by_index // // Get a klass from the constant pool. -ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool, +ciKlass* ciEnv::get_klass_by_index(const constantPoolHandle& cpool, int index, bool& is_accessible, ciInstanceKlass* accessor) { @@ -571,7 +571,7 @@ ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool, // ciEnv::get_constant_by_index_impl // // Implementation of get_constant_by_index(). -ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool, +ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool, int pool_index, int cache_index, ciInstanceKlass* accessor) { bool ignore_will_link; @@ -657,7 +657,7 @@ ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool, // Pull a constant out of the constant pool. How appropriate. // // Implementation note: this query is currently in no way cached. -ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool, +ciConstant ciEnv::get_constant_by_index(const constantPoolHandle& cpool, int pool_index, int cache_index, ciInstanceKlass* accessor) { GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, pool_index, cache_index, accessor);) @@ -737,7 +737,7 @@ Method* ciEnv::lookup_method(InstanceKlass* accessor, // ------------------------------------------------------------------ // ciEnv::get_method_by_index_impl -ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool, +ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool, int index, Bytecodes::Code bc, ciInstanceKlass* accessor) { if (bc == Bytecodes::_invokedynamic) { @@ -849,7 +849,7 @@ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* m // ------------------------------------------------------------------ // ciEnv::get_method_by_index -ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool, +ciMethod* ciEnv::get_method_by_index(const constantPoolHandle& cpool, int index, Bytecodes::Code bc, ciInstanceKlass* accessor) { GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);) diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index f50a502db0b..b1a95bd38f6 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -120,34 +120,34 @@ private: bool require_local); // Constant pool access. - ciKlass* get_klass_by_index(constantPoolHandle cpool, + ciKlass* get_klass_by_index(const constantPoolHandle& cpool, int klass_index, bool& is_accessible, ciInstanceKlass* loading_klass); - ciConstant get_constant_by_index(constantPoolHandle cpool, + ciConstant get_constant_by_index(const constantPoolHandle& cpool, int pool_index, int cache_index, ciInstanceKlass* accessor); ciField* get_field_by_index(ciInstanceKlass* loading_klass, int field_index); - ciMethod* get_method_by_index(constantPoolHandle cpool, + ciMethod* get_method_by_index(const constantPoolHandle& cpool, int method_index, Bytecodes::Code bc, ciInstanceKlass* loading_klass); // Implementation methods for loading and constant pool access. ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass, - constantPoolHandle cpool, + const constantPoolHandle& cpool, ciSymbol* klass_name, bool require_local); - ciKlass* get_klass_by_index_impl(constantPoolHandle cpool, + ciKlass* get_klass_by_index_impl(const constantPoolHandle& cpool, int klass_index, bool& is_accessible, ciInstanceKlass* loading_klass); - ciConstant get_constant_by_index_impl(constantPoolHandle cpool, + ciConstant get_constant_by_index_impl(const constantPoolHandle& cpool, int pool_index, int cache_index, ciInstanceKlass* loading_klass); ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass, int field_index); - ciMethod* get_method_by_index_impl(constantPoolHandle cpool, + ciMethod* get_method_by_index_impl(const constantPoolHandle& cpool, int method_index, Bytecodes::Code bc, ciInstanceKlass* loading_klass); diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index cfbc7b8c65f..8ed8fcef211 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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,7 +46,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : ciKlass(h_k) { - assert(get_Klass()->oop_is_instance(), "wrong type"); + assert(get_Klass()->is_instance_klass(), "wrong type"); assert(get_instanceKlass()->is_loaded(), "must be at least loaded"); InstanceKlass* ik = get_instanceKlass(); @@ -356,7 +356,7 @@ ciInstanceKlass* ciInstanceKlass::unique_concrete_subklass() { VM_ENTRY_MARK; InstanceKlass* ik = get_instanceKlass(); Klass* up = ik->up_cast_abstract(); - assert(up->oop_is_instance(), "must be InstanceKlass"); + assert(up->is_instance_klass(), "must be InstanceKlass"); if (ik == up) { return NULL; } @@ -683,7 +683,7 @@ void ciInstanceKlass::dump_replay_data(outputStream* out) { // Try to record related loaded classes Klass* sub = ik->subklass(); while (sub != NULL) { - if (sub->oop_is_instance()) { + if (sub->is_instance_klass()) { out->print_cr("instanceKlass %s", sub->name()->as_quoted_ascii()); } sub = sub->next_sibling(); diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp index 080acd380e1..b0d3234af6e 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -81,7 +81,7 @@ protected: ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain); InstanceKlass* get_instanceKlass() const { - return (InstanceKlass*)get_Klass(); + return InstanceKlass::cast(get_Klass()); } oop loader(); diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 3014c7f4a0b..0acf602a4cc 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -744,7 +744,7 @@ ciMethod* ciMethod::find_monomorphic_target(ciInstanceKlass* caller, #ifndef PRODUCT if (TraceDependencies && target() != NULL && target() != root_m->get_Method()) { tty->print("found a non-root unique target method"); - tty->print_cr(" context = %s", InstanceKlass::cast(actual_recv->get_Klass())->external_name()); + tty->print_cr(" context = %s", actual_recv->get_Klass()->external_name()); tty->print(" method = "); target->print_short_name(tty); tty->cr(); @@ -790,7 +790,7 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail. - if (h_recv->oop_is_array() + if (h_recv->is_array_klass() || InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) { if (holder()->is_interface()) { diff --git a/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp b/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp index 2b035c2af0f..d1946659fb7 100644 --- a/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp +++ b/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -39,7 +39,7 @@ // // Constructor for loaded object array klasses. ciObjArrayKlass::ciObjArrayKlass(KlassHandle h_k) : ciArrayKlass(h_k) { - assert(get_Klass()->oop_is_objArray(), "wrong type"); + assert(get_Klass()->is_objArray_klass(), "wrong type"); Klass* element_Klass = get_ObjArrayKlass()->bottom_klass(); _base_element_klass = CURRENT_ENV->get_klass(element_Klass); assert(_base_element_klass->is_instance_klass() || diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp index 295b7c9282e..240ed839bf0 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp @@ -357,7 +357,7 @@ ciMetadata* ciObjectFactory::create_new_metadata(Metadata* o) { // Hold metadata from unloading by keeping it's holder alive. if (_initialized && o->is_klass()) { Klass* holder = ((Klass*)o); - if (holder->oop_is_instance() && InstanceKlass::cast(holder)->is_anonymous()) { + if (holder->is_instance_klass() && InstanceKlass::cast(holder)->is_anonymous()) { // Though ciInstanceKlass records class loader oop, it's not enough to keep // VM anonymous classes alive (loader == NULL). Klass holder should be used instead. // It is enough to record a ciObject, since cached elements are never removed @@ -370,11 +370,11 @@ ciMetadata* ciObjectFactory::create_new_metadata(Metadata* o) { if (o->is_klass()) { KlassHandle h_k(THREAD, (Klass*)o); Klass* k = (Klass*)o; - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { return new (arena()) ciInstanceKlass(h_k); - } else if (k->oop_is_objArray()) { + } else if (k->is_objArray_klass()) { return new (arena()) ciObjArrayKlass(h_k); - } else if (k->oop_is_typeArray()) { + } else if (k->is_typeArray_klass()) { return new (arena()) ciTypeArrayKlass(h_k); } } else if (o->is_method()) { @@ -414,6 +414,7 @@ void ciObjectFactory::ensure_metadata_alive(ciMetadata* m) { metadata_owner_klass = m->as_method()->get_Method()->constants()->pool_holder(); } else { fatal("Not implemented for other types of metadata"); + return; } oop metadata_holder = metadata_owner_klass->klass_holder(); diff --git a/hotspot/src/share/vm/ci/ciReplay.cpp b/hotspot/src/share/vm/ci/ciReplay.cpp index 3e22b50d2c4..27a5c1c8c16 100644 --- a/hotspot/src/share/vm/ci/ciReplay.cpp +++ b/hotspot/src/share/vm/ci/ciReplay.cpp @@ -530,15 +530,15 @@ class CompileReplay : public StackObj { if (_imethod != NULL) { return; // Replay Inlining } - Klass* k = method->method_holder(); - ((InstanceKlass*)k)->initialize(THREAD); + InstanceKlass* ik = method->method_holder(); + ik->initialize(THREAD); if (HAS_PENDING_EXCEPTION) { oop throwable = PENDING_EXCEPTION; java_lang_Throwable::print(throwable, tty); tty->cr(); if (ReplayIgnoreInitErrors) { CLEAR_PENDING_EXCEPTION; - ((InstanceKlass*)k)->set_init_state(InstanceKlass::fully_initialized); + ik->set_init_state(InstanceKlass::fully_initialized); } else { return; } @@ -842,7 +842,7 @@ class CompileReplay : public StackObj { } else if (field_signature[0] == 'L') { Symbol* klass_name = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK); KlassHandle kelem = resolve_klass(field_signature, CHECK); - oop value = ((InstanceKlass*)kelem())->allocate_instance(CHECK); + oop value = InstanceKlass::cast(kelem())->allocate_instance(CHECK); java_mirror->obj_field_put(fd.offset(), value); } else { report_error("unhandled staticfield"); diff --git a/hotspot/src/share/vm/ci/ciSignature.cpp b/hotspot/src/share/vm/ci/ciSignature.cpp index 634ca47981c..79f80d2bf81 100644 --- a/hotspot/src/share/vm/ci/ciSignature.cpp +++ b/hotspot/src/share/vm/ci/ciSignature.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ // ------------------------------------------------------------------ // ciSignature::ciSignature -ciSignature::ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* symbol) { +ciSignature::ciSignature(ciKlass* accessing_klass, const constantPoolHandle& cpool, ciSymbol* symbol) { ASSERT_IN_VM; EXCEPTION_CONTEXT; _accessing_klass = accessing_klass; diff --git a/hotspot/src/share/vm/ci/ciSignature.hpp b/hotspot/src/share/vm/ci/ciSignature.hpp index 1d0f067c3bc..37ffdf12304 100644 --- a/hotspot/src/share/vm/ci/ciSignature.hpp +++ b/hotspot/src/share/vm/ci/ciSignature.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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,7 +46,7 @@ private: friend class ciBytecodeStream; friend class ciObjectFactory; - ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature); + ciSignature(ciKlass* accessing_klass, const constantPoolHandle& cpool, ciSymbol* signature); ciSignature(ciKlass* accessing_klass, ciSymbol* signature, ciMethodType* method_type); void get_all_klasses(); diff --git a/hotspot/src/share/vm/ci/ciType.cpp b/hotspot/src/share/vm/ci/ciType.cpp index 43df753cb49..32ba363ac6d 100644 --- a/hotspot/src/share/vm/ci/ciType.cpp +++ b/hotspot/src/share/vm/ci/ciType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ ciType::ciType(BasicType basic_type) : ciMetadata() { } ciType::ciType(KlassHandle k) : ciMetadata(k()) { - _basic_type = k()->oop_is_array() ? T_ARRAY : T_OBJECT; + _basic_type = k()->is_array_klass() ? T_ARRAY : T_OBJECT; } diff --git a/hotspot/src/share/vm/ci/ciTypeArray.cpp b/hotspot/src/share/vm/ci/ciTypeArray.cpp index 15113348e21..f85379fdb43 100644 --- a/hotspot/src/share/vm/ci/ciTypeArray.cpp +++ b/hotspot/src/share/vm/ci/ciTypeArray.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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,3 +46,13 @@ jchar ciTypeArray::char_at(int index) { #endif //ASSERT return c; } + +// ------------------------------------------------------------------ +// ciTypeArray::byte_at +// +// Implementation of the byte_at method. +jbyte ciTypeArray::byte_at(int index) { + VM_ENTRY_MARK; + assert(index >= 0 && index < length(), "out of range"); + return get_typeArrayOop()->byte_at(index); +} diff --git a/hotspot/src/share/vm/ci/ciTypeArray.hpp b/hotspot/src/share/vm/ci/ciTypeArray.hpp index 80a767d91ee..ca4c99995b4 100644 --- a/hotspot/src/share/vm/ci/ciTypeArray.hpp +++ b/hotspot/src/share/vm/ci/ciTypeArray.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -56,6 +56,9 @@ public: // array will never change. jchar char_at(int index); + // Return byte at index. + jbyte byte_at(int index); + }; #endif // SHARE_VM_CI_CITYPEARRAY_HPP diff --git a/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp b/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp index 991fc283127..4b1e4ba603b 100644 --- a/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp +++ b/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -34,7 +34,7 @@ // ------------------------------------------------------------------ // ciTypeArrayKlass::ciTypeArrayKlass ciTypeArrayKlass::ciTypeArrayKlass(KlassHandle h_k) : ciArrayKlass(h_k) { - assert(get_Klass()->oop_is_typeArray(), "wrong type"); + assert(get_Klass()->is_typeArray_klass(), "wrong type"); assert(element_type() == get_TypeArrayKlass()->element_type(), ""); } diff --git a/hotspot/src/share/vm/classfile/bytecodeAssembler.hpp b/hotspot/src/share/vm/classfile/bytecodeAssembler.hpp index 74301472a63..01e338e0b55 100644 --- a/hotspot/src/share/vm/classfile/bytecodeAssembler.hpp +++ b/hotspot/src/share/vm/classfile/bytecodeAssembler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 @@ -140,7 +140,7 @@ class BytecodeConstantPool : ResourceObj { BytecodeCPEntry const& at(u2 index) const { return _entries.at(index); } InstanceKlass* pool_holder() const { - return InstanceKlass::cast(_orig->pool_holder()); + return _orig->pool_holder(); } u2 utf8(Symbol* sym) { diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 3e1f13de4ea..c9296533878 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -92,6 +92,7 @@ // Used for backward compatibility reasons: // - to check NameAndType_info signatures more aggressively +// - to disallow argument and require ACC_STATIC for methods #define JAVA_7_VERSION 51 // Extension method support. @@ -315,6 +316,7 @@ inline Symbol* check_symbol_at(constantPoolHandle cp, int index) { return NULL; } +#ifdef ASSERT PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED void ClassFileParser::report_assert_property_failure(const char* msg, TRAPS) { @@ -327,6 +329,7 @@ void ClassFileParser::report_assert_property_failure(const char* msg, int index, fatal(msg, index, _class_name->as_C_string()); } PRAGMA_DIAG_POP +#endif constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { ClassFileStream* cfs = stream(); @@ -646,7 +649,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { } -void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS) { +void ClassFileParser::patch_constant_pool(const constantPoolHandle& cp, int index, Handle patch, TRAPS) { BasicType patch_type = T_VOID; switch (cp->tag_at(index).value()) { @@ -822,7 +825,7 @@ Array* ClassFileParser::parse_interfaces(int length, debug_only(No_Safepoint_Verifier nsv;) for (index = 0; index < length; index++) { Klass* k = _local_interfaces->at(index); - Symbol* name = InstanceKlass::cast(k)->name(); + Symbol* name = k->name(); // If no duplicates, add (name, NULL) in hashtable interface_names. if (!put_after_lookup(name, NULL, interface_names)) { dup = true; @@ -1995,9 +1998,7 @@ methodHandle ClassFileParser::parse_method(bool is_interface, } else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) { flags &= JVM_ACC_STATIC | JVM_ACC_STRICT; } else { - // As of major_version 51, a method named without ACC_STATIC is - // just another method. So, do a normal method modifer check. - verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle)); + classfile_parse_error("Method is not static in class file %s", CHECK_(nullHandle)); } } else { verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle)); @@ -3175,8 +3176,9 @@ instanceKlassHandle ClassFileParser::parse_super_class(int super_class_index, bool is_array = false; if (_cp->tag_at(super_class_index).is_klass()) { super_klass = instanceKlassHandle(THREAD, _cp->resolved_klass_at(super_class_index)); - if (_need_verify) - is_array = super_klass->oop_is_array(); + if (_need_verify) { + is_array = super_klass->is_array_klass(); + } } else if (_need_verify) { is_array = (_cp->klass_name_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY); } @@ -3211,19 +3213,19 @@ void ClassFileParser::layout_fields(Handle class_loader, // Field size and offset computation int nonstatic_field_size = _super_klass() == NULL ? 0 : _super_klass()->nonstatic_field_size(); - int next_static_oop_offset; - int next_static_double_offset; - int next_static_word_offset; - int next_static_short_offset; - int next_static_byte_offset; - int next_nonstatic_oop_offset; - int next_nonstatic_double_offset; - int next_nonstatic_word_offset; - int next_nonstatic_short_offset; - int next_nonstatic_byte_offset; - int first_nonstatic_oop_offset; - int next_nonstatic_field_offset; - int next_nonstatic_padded_offset; + int next_static_oop_offset = 0; + int next_static_double_offset = 0; + int next_static_word_offset = 0; + int next_static_short_offset = 0; + int next_static_byte_offset = 0; + int next_nonstatic_oop_offset = 0; + int next_nonstatic_double_offset = 0; + int next_nonstatic_word_offset = 0; + int next_nonstatic_short_offset = 0; + int next_nonstatic_byte_offset = 0; + int first_nonstatic_oop_offset = 0; + int next_nonstatic_field_offset = 0; + int next_nonstatic_padded_offset = 0; // Count the contended fields by type. // @@ -3376,14 +3378,14 @@ void ClassFileParser::layout_fields(Handle class_loader, ShouldNotReachHere(); } - int nonstatic_oop_space_count = 0; - int nonstatic_word_space_count = 0; - int nonstatic_short_space_count = 0; - int nonstatic_byte_space_count = 0; - int nonstatic_oop_space_offset; - int nonstatic_word_space_offset; - int nonstatic_short_space_offset; - int nonstatic_byte_space_offset; + int nonstatic_oop_space_count = 0; + int nonstatic_word_space_count = 0; + int nonstatic_short_space_count = 0; + int nonstatic_byte_space_count = 0; + int nonstatic_oop_space_offset = 0; + int nonstatic_word_space_offset = 0; + int nonstatic_short_space_offset = 0; + int nonstatic_byte_space_offset = 0; // Try to squeeze some of the fields into the gaps due to // long/double alignment. @@ -3455,7 +3457,7 @@ void ClassFileParser::layout_fields(Handle class_loader, // contended instance fields are handled below if (fs.is_contended() && !fs.access_flags().is_static()) continue; - int real_offset; + int real_offset = 0; FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); // pack the rest of the fields @@ -3589,7 +3591,7 @@ void ClassFileParser::layout_fields(Handle class_loader, // handle statics below if (fs.access_flags().is_static()) continue; - int real_offset; + int real_offset = 0; FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); switch (atype) { @@ -4111,7 +4113,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, this_klass->set_should_verify_class(verify); jint lh = Klass::instance_layout_helper(info.instance_size, false); this_klass->set_layout_helper(lh); - assert(this_klass->oop_is_instance(), "layout is correct"); + assert(this_klass->is_instance_klass(), "layout is correct"); assert(this_klass->size_helper() == info.instance_size, "correct size_helper"); // Not yet: supers are done below to support the new subtype-checking fields //this_klass->set_super(super_klass()); @@ -4315,13 +4317,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, if (caller != NULL) { tty->print("[Loaded %s by instance of %s]\n", this_klass->external_name(), - InstanceKlass::cast(caller)->external_name()); + caller->external_name()); } else { tty->print("[Loaded %s]\n", this_klass->external_name()); } } else { tty->print("[Loaded %s from %s]\n", this_klass->external_name(), - InstanceKlass::cast(class_loader->klass())->external_name()); + class_loader->klass()->external_name()); } } @@ -4330,7 +4332,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // print out the superclass. const char * from = this_klass()->external_name(); if (this_klass->java_super() != NULL) { - tty->print("RESOLVE %s %s (super)\n", from, InstanceKlass::cast(this_klass->java_super())->external_name()); + tty->print("RESOLVE %s %s (super)\n", from, this_klass->java_super()->external_name()); } // print out each of the interface classes referred to by this class. Array* local_interfaces = this_klass->local_interfaces(); @@ -4338,8 +4340,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, int length = local_interfaces->length(); for (int i = 0; i < length; i++) { Klass* k = local_interfaces->at(i); - InstanceKlass* to_class = InstanceKlass::cast(k); - const char * to = to_class->external_name(); + const char * to = k->external_name(); tty->print("RESOLVE %s %s (interface)\n", from, to); } } @@ -4411,7 +4412,7 @@ ClassFileParser::~ClassFileParser() { void ClassFileParser::print_field_layout(Symbol* name, Array* fields, - constantPoolHandle cp, + const constantPoolHandle& cp, int instance_size, int instance_fields_start, int instance_fields_end, @@ -4687,7 +4688,7 @@ void ClassFileParser::check_super_class_access(instanceKlassHandle this_klass, T vmSymbols::java_lang_IllegalAccessError(), "class %s cannot access its superclass %s", this_klass->external_name(), - InstanceKlass::cast(super)->external_name() + super->external_name() ); return; } @@ -4707,7 +4708,7 @@ void ClassFileParser::check_super_interface_access(instanceKlassHandle this_klas vmSymbols::java_lang_IllegalAccessError(), "class %s cannot access its superinterface %s", this_klass->external_name(), - InstanceKlass::cast(k)->external_name() + k->external_name() ); return; } @@ -5157,6 +5158,14 @@ int ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signatu return -2; } + // Class initializers cannot have args for class format version >= 51. + if (name == vmSymbols::class_initializer_name() && + signature != vmSymbols::void_method_signature() && + _major_version >= JAVA_7_VERSION) { + throwIllegalSignature("Method", name, signature, CHECK_0); + return 0; + } + unsigned int args_size = 0; char buf[fixed_buffer_size]; char* p = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); @@ -5180,8 +5189,8 @@ int ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signatu // The first non-signature thing better be a ')' if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) { length--; - if (name == vmSymbols::object_initializer_name()) { - // All "" methods must return void + if (name->utf8_length() > 0 && name->byte_at(0) == '<') { + // All internal methods must return void if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) { return args_size; } diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index 10d331fa641..fc9b7a0c179 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.hpp +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp @@ -241,7 +241,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { void print_field_layout(Symbol* name, Array* fields, - constantPoolHandle cp, + const constantPoolHandle& cp, int instance_size, int instance_fields_start, int instance_fields_end, @@ -319,8 +319,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { if (!b) { classfile_parse_error(msg, CHECK); } } - void report_assert_property_failure(const char* msg, TRAPS); - void report_assert_property_failure(const char* msg, int index, TRAPS); + void report_assert_property_failure(const char* msg, TRAPS) PRODUCT_RETURN; + void report_assert_property_failure(const char* msg, int index, TRAPS) PRODUCT_RETURN; inline void assert_property(bool b, const char* msg, TRAPS) { #ifdef ASSERT @@ -403,7 +403,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { assert(!has_cp_patch_at(index), ""); return patch; } - void patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS); + void patch_constant_pool(const constantPoolHandle& cp, int index, Handle patch, TRAPS); // Wrapper for constantTag.is_klass_[or_]reference. // In older versions of the VM, Klass*s cannot sneak into early phases of diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index d1ff1c3cbab..3d0727ed67e 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -140,7 +140,7 @@ void ClassLoaderData::classes_do(void f(Klass * const)) { void ClassLoaderData::methods_do(void f(Method*)) { for (Klass* k = _klasses; k != NULL; k = k->next_link()) { - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { InstanceKlass::cast(k)->methods_do(f); } } @@ -151,7 +151,7 @@ void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) { MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); for (Klass* k = _klasses; k != NULL; k = k->next_link()) { // Do not filter ArrayKlass oops here... - if (k->oop_is_array() || (k->oop_is_instance() && InstanceKlass::cast(k)->is_loaded())) { + if (k->is_array_klass() || (k->is_instance_klass() && InstanceKlass::cast(k)->is_loaded())) { klass_closure->do_klass(k); } } @@ -159,7 +159,7 @@ void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) { void ClassLoaderData::classes_do(void f(InstanceKlass*)) { for (Klass* k = _klasses; k != NULL; k = k->next_link()) { - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { f(InstanceKlass::cast(k)); } assert(k != k->next_link(), "no loops!"); diff --git a/hotspot/src/share/vm/classfile/compactHashtable.cpp b/hotspot/src/share/vm/classfile/compactHashtable.cpp index 0026d88ec88..39dd55f9a17 100644 --- a/hotspot/src/share/vm/classfile/compactHashtable.cpp +++ b/hotspot/src/share/vm/classfile/compactHashtable.cpp @@ -422,7 +422,7 @@ int HashtableTextDump::scan_prefix(int* utf8_length) { int HashtableTextDump::scan_string_prefix() { // Expect /[0-9]+: / - int utf8_length; + int utf8_length = 0; get_num(':', &utf8_length); if (*_p != ' ') { corrupted(_p, "Wrong prefix format for string"); @@ -433,13 +433,13 @@ int HashtableTextDump::scan_string_prefix() { int HashtableTextDump::scan_symbol_prefix() { // Expect /[0-9]+ (-|)[0-9]+: / - int utf8_length; + int utf8_length = 0; get_num(' ', &utf8_length); - if (*_p == '-') { - _p++; + if (*_p == '-') { + _p++; } int ref_num; - (void)get_num(':', &ref_num); + get_num(':', &ref_num); if (*_p != ' ') { corrupted(_p, "Wrong prefix format for symbol"); } diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp index fdd2170faaa..7c5038fd391 100644 --- a/hotspot/src/share/vm/classfile/defaultMethods.cpp +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp @@ -26,6 +26,7 @@ #include "classfile/bytecodeAssembler.hpp" #include "classfile/defaultMethods.hpp" #include "classfile/symbolTable.hpp" +#include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/metadataFactory.hpp" #include "memory/resourceArea.hpp" @@ -74,7 +75,6 @@ class PseudoScope : public ResourceObj { } }; -#ifndef PRODUCT static void print_slot(outputStream* str, Symbol* name, Symbol* signature) { ResourceMark rm; str->print("%s%s", name->as_C_string(), signature->as_C_string()); @@ -87,7 +87,6 @@ static void print_method(outputStream* str, Method* mo, bool with_class=true) { } print_slot(str, mo->name(), mo->signature()); } -#endif // ndef PRODUCT /** * Perform a depth-first iteration over the class hierarchy, applying @@ -246,21 +245,22 @@ class HierarchyVisitor : StackObj { } }; -#ifndef PRODUCT class PrintHierarchy : public HierarchyVisitor { + private: + outputStream* _st; public: - bool visit() { InstanceKlass* cls = current_class(); - streamIndentor si(tty, current_depth() * 2); - tty->indent().print_cr("%s", cls->name()->as_C_string()); + streamIndentor si(_st, current_depth() * 2); + _st->indent().print_cr("%s", cls->name()->as_C_string()); return true; } void* new_node_data(InstanceKlass* cls) { return NULL; } void free_node_data(void* data) { return; } + + PrintHierarchy(outputStream* st = tty) : _st(st) {} }; -#endif // ndef PRODUCT // Used to register InstanceKlass objects and all related metadata structures // (Methods, ConstantPools) as "in-use" by the current thread so that they can't @@ -434,9 +434,11 @@ class MethodFamily : public ResourceObj { } else if (num_defaults > 1) { _exception_message = generate_conflicts_message(&qualified_methods,CHECK); _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); - if (TraceDefaultMethods) { - _exception_message->print_value_on(tty); - tty->cr(); + if (log_is_enabled(Debug, defaultmethods)) { + ResourceMark rm; + outputStream* logstream = LogHandle(defaultmethods)::debug_stream(); + _exception_message->print_value_on(logstream); + logstream->cr(); } } } @@ -450,27 +452,6 @@ class MethodFamily : public ResourceObj { return false; } -#ifndef PRODUCT - void print_sig_on(outputStream* str, Symbol* signature, int indent) const { - streamIndentor si(str, indent * 2); - - str->indent().print_cr("Logical Method %s:", signature->as_C_string()); - - streamIndentor si2(str); - for (int i = 0; i < _members.length(); ++i) { - str->indent(); - print_method(str, _members.at(i).first); - if (_members.at(i).second == DISQUALIFIED) { - str->print(" (disqualified)"); - } - str->cr(); - } - - if (_selected_target != NULL) { - print_selected(str, 1); - } - } - void print_selected(outputStream* str, int indent) const { assert(has_target(), "Should be called otherwise"); streamIndentor si(str, indent * 2); @@ -478,7 +459,7 @@ class MethodFamily : public ResourceObj { print_method(str, _selected_target); Klass* method_holder = _selected_target->method_holder(); if (!method_holder->is_interface()) { - tty->print(" : in superclass"); + str->print(" : in superclass"); } str->cr(); } @@ -489,7 +470,6 @@ class MethodFamily : public ResourceObj { streamIndentor si(str, indent * 2); str->indent().print_cr("%s: %s", _exception_name->as_C_string(), _exception_message->as_C_string()); } -#endif // ndef PRODUCT }; Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const { @@ -608,11 +588,9 @@ class EmptyVtableSlot : public ResourceObj { bool is_bound() { return _binding != NULL; } MethodFamily* get_binding() { return _binding; } -#ifndef PRODUCT void print_on(outputStream* str) const { print_slot(str, name(), signature()); } -#endif // ndef PRODUCT }; static bool already_in_vtable_slots(GrowableArray* slots, Method* m) { @@ -681,17 +659,18 @@ static GrowableArray* find_empty_vtable_slots( super = super->java_super(); } -#ifndef PRODUCT - if (TraceDefaultMethods) { - tty->print_cr("Slots that need filling:"); - streamIndentor si(tty); + if (log_is_enabled(Debug, defaultmethods)) { + log_debug(defaultmethods)("Slots that need filling:"); + ResourceMark rm; + outputStream* logstream = LogHandle(defaultmethods)::debug_stream(); + streamIndentor si(logstream); for (int i = 0; i < slots->length(); ++i) { - tty->indent(); - slots->at(i)->print_on(tty); - tty->cr(); + logstream->indent(); + slots->at(i)->print_on(logstream); + logstream->cr(); } } -#endif // ndef PRODUCT + return slots; } @@ -812,46 +791,32 @@ void DefaultMethods::generate_default_methods( KeepAliveVisitor loadKeepAlive(&keepAlive); loadKeepAlive.run(klass); -#ifndef PRODUCT - if (TraceDefaultMethods) { - ResourceMark rm; // be careful with these! - tty->print_cr("%s %s requires default method processing", - klass->is_interface() ? "Interface" : "Class", - klass->name()->as_klass_external_name()); - PrintHierarchy printer; + if (log_is_enabled(Debug, defaultmethods)) { + ResourceMark rm; + log_debug(defaultmethods)("%s %s requires default method processing", + klass->is_interface() ? "Interface" : "Class", + klass->name()->as_klass_external_name()); + PrintHierarchy printer(LogHandle(defaultmethods)::debug_stream()); printer.run(klass); } -#endif // ndef PRODUCT GrowableArray* empty_slots = find_empty_vtable_slots(klass, mirandas, CHECK); for (int i = 0; i < empty_slots->length(); ++i) { EmptyVtableSlot* slot = empty_slots->at(i); -#ifndef PRODUCT - if (TraceDefaultMethods) { - streamIndentor si(tty, 2); - tty->indent().print("Looking for default methods for slot "); - slot->print_on(tty); - tty->cr(); + if (log_is_enabled(Debug, defaultmethods)) { + outputStream* logstream = LogHandle(defaultmethods)::debug_stream(); + streamIndentor si(logstream, 2); + logstream->indent().print("Looking for default methods for slot "); + slot->print_on(logstream); + logstream->cr(); } -#endif // ndef PRODUCT - generate_erased_defaults(klass, empty_slots, slot, CHECK); - } -#ifndef PRODUCT - if (TraceDefaultMethods) { - tty->print_cr("Creating defaults and overpasses..."); } -#endif // ndef PRODUCT - + log_debug(defaultmethods)("Creating defaults and overpasses..."); create_defaults_and_exceptions(empty_slots, klass, CHECK); - -#ifndef PRODUCT - if (TraceDefaultMethods) { - tty->print_cr("Default method processing complete"); - } -#endif // ndef PRODUCT + log_debug(defaultmethods)("Default method processing complete"); } static int assemble_method_error( @@ -947,18 +912,18 @@ static void create_defaults_and_exceptions( MethodFamily* method = slot->get_binding(); BytecodeBuffer buffer; -#ifndef PRODUCT - if (TraceDefaultMethods) { - tty->print("for slot: "); - slot->print_on(tty); - tty->cr(); + if (log_is_enabled(Debug, defaultmethods)) { + ResourceMark rm; + outputStream* logstream = LogHandle(defaultmethods)::debug_stream(); + logstream->print("for slot: "); + slot->print_on(logstream); + logstream->cr(); if (method->has_target()) { - method->print_selected(tty, 1); + method->print_selected(logstream, 1); } else if (method->throws_exception()) { - method->print_exception(tty, 1); + method->print_exception(logstream, 1); } } -#endif // ndef PRODUCT if (method->has_target()) { Method* selected = method->get_selected_target(); @@ -982,12 +947,9 @@ static void create_defaults_and_exceptions( } } -#ifndef PRODUCT - if (TraceDefaultMethods) { - tty->print_cr("Created %d overpass methods", overpasses.length()); - tty->print_cr("Created %d default methods", defaults.length()); - } -#endif // ndef PRODUCT + + log_debug(defaultmethods)("Created %d overpass methods", overpasses.length()); + log_debug(defaultmethods)("Created %d default methods", defaults.length()); if (overpasses.length() > 0) { switchover_constant_pool(&bpool, klass, &overpasses, CHECK); diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index 3621af33f83..82e4e71cf81 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -60,7 +60,7 @@ DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass, DictionaryEntry* entry = (DictionaryEntry*)Hashtable::new_entry(hash, klass); entry->set_loader_data(loader_data); entry->set_pd_set(NULL); - assert(klass->oop_is_instance(), "Must be"); + assert(klass->is_instance_klass(), "Must be"); return entry; } @@ -78,7 +78,7 @@ void Dictionary::free_entry(DictionaryEntry* entry) { bool DictionaryEntry::contains_protection_domain(oop protection_domain) const { #ifdef ASSERT - if (protection_domain == InstanceKlass::cast(klass())->protection_domain()) { + if (protection_domain == klass()->protection_domain()) { // Ensure this doesn't show up in the pd_set (invariant) bool in_pd_set = false; for (ProtectionDomainEntry* current = _pd_set; @@ -96,7 +96,7 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const { } #endif /* ASSERT */ - if (protection_domain == InstanceKlass::cast(klass())->protection_domain()) { + if (protection_domain == klass()->protection_domain()) { // Succeeds trivially return true; } @@ -275,7 +275,7 @@ void Dictionary::classes_do(void f(Klass*)) { probe != NULL; probe = probe->next()) { Klass* k = probe->klass(); - if (probe->loader_data() == InstanceKlass::cast(k)->class_loader_data()) { + if (probe->loader_data() == k->class_loader_data()) { f(k); } } @@ -290,7 +290,7 @@ void Dictionary::classes_do(void f(Klass*, TRAPS), TRAPS) { probe != NULL; probe = probe->next()) { Klass* k = probe->klass(); - if (probe->loader_data() == InstanceKlass::cast(k)->class_loader_data()) { + if (probe->loader_data() == k->class_loader_data()) { f(k, CHECK); } } @@ -322,7 +322,7 @@ void Dictionary::methods_do(void f(Method*)) { probe != NULL; probe = probe->next()) { Klass* k = probe->klass(); - if (probe->loader_data() == InstanceKlass::cast(k)->class_loader_data()) { + if (probe->loader_data() == k->class_loader_data()) { // only take klass is we have the entry with the defining class loader InstanceKlass::cast(k)->methods_do(f); } @@ -476,7 +476,7 @@ void Dictionary::reorder_dictionary() { DictionaryEntry* p = master_list; master_list = master_list->next(); p->set_next(NULL); - Symbol* class_name = InstanceKlass::cast((Klass*)(p->klass()))->name(); + Symbol* class_name = p->klass()->name(); // Since the null class loader data isn't copied to the CDS archive, // compute the hash with NULL for loader data. unsigned int hash = compute_hash(class_name, NULL); @@ -723,7 +723,7 @@ void Dictionary::print(bool details) { Klass* e = probe->klass(); ClassLoaderData* loader_data = probe->loader_data(); bool is_defining_class = - (loader_data == InstanceKlass::cast(e)->class_loader_data()); + (loader_data == e->class_loader_data()); tty->print("%s%s", ((!details) || is_defining_class) ? " " : "^", e->external_name()); @@ -756,7 +756,7 @@ void Dictionary::verify() { probe = probe->next()) { Klass* e = probe->klass(); ClassLoaderData* loader_data = probe->loader_data(); - guarantee(e->oop_is_instance(), + guarantee(e->is_instance_klass(), "Verify of system dictionary failed"); // class loader must be present; a null class loader is the // boostrap loader diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp index 7ce8d34e5f5..1f6b568670e 100644 --- a/hotspot/src/share/vm/classfile/dictionary.hpp +++ b/hotspot/src/share/vm/classfile/dictionary.hpp @@ -323,8 +323,7 @@ class DictionaryEntry : public HashtableEntry { bool equals(Symbol* class_name, ClassLoaderData* loader_data) const { Klass* klass = (Klass*)literal(); - return (InstanceKlass::cast(klass)->name() == class_name && - _loader_data == loader_data); + return (klass->name() == class_name && _loader_data == loader_data); } void print() { diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index fcdb0e0c6e5..a9f7c4616c6 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -114,17 +114,17 @@ static bool find_field(InstanceKlass* ik, // Helpful routine for computing field offsets at run time rather than hardcoding them static void compute_offset(int &dest_offset, - Klass* klass_oop, Symbol* name_symbol, Symbol* signature_symbol, + Klass* klass, Symbol* name_symbol, Symbol* signature_symbol, bool is_static = false, bool allow_super = false) { fieldDescriptor fd; - InstanceKlass* ik = InstanceKlass::cast(klass_oop); + InstanceKlass* ik = InstanceKlass::cast(klass); if (!find_field(ik, name_symbol, signature_symbol, &fd, is_static, allow_super)) { ResourceMark rm; tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); #ifndef PRODUCT - klass_oop->print(); + ik->print(); tty->print_cr("all fields:"); - for (AllFieldStream fs(InstanceKlass::cast(klass_oop)); !fs.done(); fs.next()) { + for (AllFieldStream fs(ik); !fs.done(); fs.next()) { tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); } #endif //PRODUCT @@ -136,10 +136,10 @@ compute_offset(int &dest_offset, // Same as above but for "optional" offsets that might not be present in certain JDK versions static void compute_optional_offset(int& dest_offset, - Klass* klass_oop, Symbol* name_symbol, Symbol* signature_symbol, + Klass* klass, Symbol* name_symbol, Symbol* signature_symbol, bool allow_super = false) { fieldDescriptor fd; - InstanceKlass* ik = InstanceKlass::cast(klass_oop); + InstanceKlass* ik = InstanceKlass::cast(klass); if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) { dest_offset = fd.offset(); } @@ -147,9 +147,8 @@ compute_optional_offset(int& dest_offset, int java_lang_String::value_offset = 0; -int java_lang_String::offset_offset = 0; -int java_lang_String::count_offset = 0; int java_lang_String::hash_offset = 0; +int java_lang_String::coder_offset = 0; bool java_lang_String::initialized = false; @@ -161,44 +160,85 @@ void java_lang_String::compute_offsets() { assert(!initialized, "offsets should be initialized only once"); Klass* k = SystemDictionary::String_klass(); - compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::char_array_signature()); - compute_optional_offset(offset_offset, k, vmSymbols::offset_name(), vmSymbols::int_signature()); - compute_optional_offset(count_offset, k, vmSymbols::count_name(), vmSymbols::int_signature()); + compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::byte_array_signature()); compute_optional_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature()); + compute_optional_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature()); initialized = true; } -Handle java_lang_String::basic_create(int length, TRAPS) { +class CompactStringsFixup : public FieldClosure { +private: + bool _value; + +public: + CompactStringsFixup(bool value) : _value(value) {} + + void do_field(fieldDescriptor* fd) { + if (fd->name() == vmSymbols::compact_strings_name()) { + oop mirror = fd->field_holder()->java_mirror(); + assert(fd->field_holder() == SystemDictionary::String_klass(), "Should be String"); + assert(mirror != NULL, "String must have mirror already"); + mirror->bool_field_put(fd->offset(), _value); + } + } +}; + +void java_lang_String::set_compact_strings(bool value) { + CompactStringsFixup fix(value); + InstanceKlass::cast(SystemDictionary::String_klass())->do_local_static_fields(&fix); +} + +Handle java_lang_String::basic_create(int length, bool is_latin1, TRAPS) { assert(initialized, "Must be initialized"); + assert(CompactStrings || !is_latin1, "Must be UTF16 without CompactStrings"); + // Create the String object first, so there's a chance that the String // and the char array it points to end up in the same cache line. oop obj; - obj = InstanceKlass::cast(SystemDictionary::String_klass())->allocate_instance(CHECK_NH); + obj = SystemDictionary::String_klass()->allocate_instance(CHECK_NH); // Create the char array. The String object must be handlized here // because GC can happen as a result of the allocation attempt. Handle h_obj(THREAD, obj); - typeArrayOop buffer; - buffer = oopFactory::new_charArray(length, CHECK_NH); + int arr_length = is_latin1 ? length : length << 1; // 2 bytes per UTF16. + typeArrayOop buffer = oopFactory::new_byteArray(arr_length, CHECK_NH);; // Point the String at the char array obj = h_obj(); set_value(obj, buffer); // No need to zero the offset, allocation zero'ed the entire String object - assert(offset(obj) == 0, "initial String offset should be zero"); -//set_offset(obj, 0); - set_count(obj, length); - + set_coder(obj, is_latin1 ? CODER_LATIN1 : CODER_UTF16); return h_obj; } Handle java_lang_String::create_from_unicode(jchar* unicode, int length, TRAPS) { - Handle h_obj = basic_create(length, CHECK_NH); + bool is_latin1 = CompactStrings && UNICODE::is_latin1(unicode, length); + Handle h_obj = basic_create(length, is_latin1, CHECK_NH); typeArrayOop buffer = value(h_obj()); - for (int index = 0; index < length; index++) { - buffer->char_at_put(index, unicode[index]); + assert(TypeArrayKlass::cast(buffer->klass())->element_type() == T_BYTE, "only byte[]"); + if (is_latin1) { + for (int index = 0; index < length; index++) { + buffer->byte_at_put(index, (jbyte)unicode[index]); + } + } else { + for (int index = 0; index < length; index++) { + buffer->char_at_put(index, unicode[index]); + } } + +#ifdef ASSERT + { + ResourceMark rm; + char* expected = UNICODE::as_utf8(unicode, length); + char* actual = as_utf8_string(h_obj()); + if (strcmp(expected, actual) != 0) { + tty->print_cr("Unicode conversion failure: %s --> %s", expected, actual); + ShouldNotReachHere(); + } + } +#endif + return h_obj; } @@ -211,11 +251,40 @@ Handle java_lang_String::create_from_str(const char* utf8_str, TRAPS) { if (utf8_str == NULL) { return Handle(); } - int length = UTF8::unicode_length(utf8_str); - Handle h_obj = basic_create(length, CHECK_NH); - if (length > 0) { - UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length); + bool has_multibyte, is_latin1; + int length = UTF8::unicode_length(utf8_str, is_latin1, has_multibyte); + if (!CompactStrings) { + has_multibyte = true; + is_latin1 = false; } + + Handle h_obj = basic_create(length, is_latin1, CHECK_NH); + if (length > 0) { + if (!has_multibyte) { + strncpy((char*)value(h_obj())->byte_at_addr(0), utf8_str, length); + } else if (is_latin1) { + UTF8::convert_to_unicode(utf8_str, value(h_obj())->byte_at_addr(0), length); + } else { + UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length); + } + } + +#ifdef ASSERT + // This check is too strict because the input string is not necessarily valid UTF8. + // For example, it may be created with arbitrary content via jni_NewStringUTF. + /* + { + ResourceMark rm; + const char* expected = utf8_str; + char* actual = as_utf8_string(h_obj()); + if (strcmp(expected, actual) != 0) { + tty->print_cr("String conversion failure: %s --> %s", expected, actual); + ShouldNotReachHere(); + } + } + */ +#endif + return h_obj; } @@ -225,11 +294,39 @@ oop java_lang_String::create_oop_from_str(const char* utf8_str, TRAPS) { } Handle java_lang_String::create_from_symbol(Symbol* symbol, TRAPS) { - int length = UTF8::unicode_length((char*)symbol->bytes(), symbol->utf8_length()); - Handle h_obj = basic_create(length, CHECK_NH); - if (length > 0) { - UTF8::convert_to_unicode((char*)symbol->bytes(), value(h_obj())->char_at_addr(0), length); + const char* utf8_str = (char*)symbol->bytes(); + int utf8_len = symbol->utf8_length(); + + bool has_multibyte, is_latin1; + int length = UTF8::unicode_length(utf8_str, utf8_len, is_latin1, has_multibyte); + if (!CompactStrings) { + has_multibyte = true; + is_latin1 = false; } + + Handle h_obj = basic_create(length, is_latin1, CHECK_NH); + if (length > 0) { + if (!has_multibyte) { + strncpy((char*)value(h_obj())->byte_at_addr(0), utf8_str, length); + } else if (is_latin1) { + UTF8::convert_to_unicode(utf8_str, value(h_obj())->byte_at_addr(0), length); + } else { + UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length); + } + } + +#ifdef ASSERT + { + ResourceMark rm; + const char* expected = symbol->as_utf8(); + char* actual = as_utf8_string(h_obj()); + if (strncmp(expected, actual, utf8_len) != 0) { + tty->print_cr("Symbol conversion failure: %s --> %s", expected, actual); + ShouldNotReachHere(); + } + } +#endif + return h_obj; } @@ -261,7 +358,6 @@ Handle java_lang_String::create_from_platform_dependent_str(const char* str, TRA // Converts a Java String to a native C string that can be used for // native OS calls. char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) { - typedef char* (*to_platform_string_fn_t)(JNIEnv*, jstring, bool*); static to_platform_string_fn_t _to_platform_string_fn = NULL; @@ -292,13 +388,15 @@ Handle java_lang_String::char_converter(Handle java_string, jchar from_char, jch oop obj = java_string(); // Typical usage is to convert all '/' to '.' in string. typeArrayOop value = java_lang_String::value(obj); - int offset = java_lang_String::offset(obj); int length = java_lang_String::length(obj); + bool is_latin1 = java_lang_String::is_latin1(obj); // First check if any from_char exist int index; // Declared outside, used later for (index = 0; index < length; index++) { - if (value->char_at(index + offset) == from_char) { + jchar c = !is_latin1 ? value->char_at(index) : + ((jchar) value->byte_at(index)) & 0xff; + if (c == from_char) { break; } } @@ -307,34 +405,66 @@ Handle java_lang_String::char_converter(Handle java_string, jchar from_char, jch return java_string; } - // Create new UNICODE buffer. Must handlize value because GC + // Check if result string will be latin1 + bool to_is_latin1 = false; + + // Replacement char must be latin1 + if (CompactStrings && UNICODE::is_latin1(to_char)) { + if (is_latin1) { + // Source string is latin1 as well + to_is_latin1 = true; + } else if (!UNICODE::is_latin1(from_char)) { + // We are replacing an UTF16 char. Scan string to + // check if result can be latin1 encoded. + to_is_latin1 = true; + for (index = 0; index < length; index++) { + jchar c = value->char_at(index); + if (c != from_char && !UNICODE::is_latin1(c)) { + to_is_latin1 = false; + break; + } + } + } + } + + // Create new UNICODE (or byte) buffer. Must handlize value because GC // may happen during String and char array creation. typeArrayHandle h_value(THREAD, value); - Handle string = basic_create(length, CHECK_NH); - + Handle string = basic_create(length, to_is_latin1, CHECK_NH); typeArrayOop from_buffer = h_value(); - typeArrayOop to_buffer = java_lang_String::value(string()); + typeArrayOop to_buffer = java_lang_String::value(string()); // Copy contents for (index = 0; index < length; index++) { - jchar c = from_buffer->char_at(index + offset); + jchar c = (!is_latin1) ? from_buffer->char_at(index) : + ((jchar) from_buffer->byte_at(index)) & 0xff; if (c == from_char) { c = to_char; } - to_buffer->char_at_put(index, c); + if (!to_is_latin1) { + to_buffer->char_at_put(index, c); + } else { + to_buffer->byte_at_put(index, (jbyte) c); + } } return string; } jchar* java_lang_String::as_unicode_string(oop java_string, int& length, TRAPS) { typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); length = java_lang_String::length(java_string); + bool is_latin1 = java_lang_String::is_latin1(java_string); jchar* result = NEW_RESOURCE_ARRAY_RETURN_NULL(jchar, length); if (result != NULL) { - for (int index = 0; index < length; index++) { - result[index] = value->char_at(index + offset); + if (!is_latin1) { + for (int index = 0; index < length; index++) { + result[index] = value->char_at(index); + } + } else { + for (int index = 0; index < length; index++) { + result[index] = ((jchar) value->byte_at(index)) & 0xff; + } } } else { THROW_MSG_0(vmSymbols::java_lang_OutOfMemoryError(), "could not allocate Unicode string"); @@ -348,21 +478,35 @@ unsigned int java_lang_String::hash_code(oop java_string) { if (length == 0) return 0; typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); - return java_lang_String::hash_code(value->char_at_addr(offset), length); + bool is_latin1 = java_lang_String::is_latin1(java_string); + + if (is_latin1) { + return java_lang_String::hash_code(value->byte_at_addr(0), length); + } else { + return java_lang_String::hash_code(value->char_at_addr(0), length); + } } char* java_lang_String::as_quoted_ascii(oop java_string) { typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); + bool is_latin1 = java_lang_String::is_latin1(java_string); - jchar* base = (length == 0) ? NULL : value->char_at_addr(offset); - if (base == NULL) return NULL; + if (length == 0) return NULL; - int result_length = UNICODE::quoted_ascii_length(base, length) + 1; - char* result = NEW_RESOURCE_ARRAY(char, result_length); - UNICODE::as_quoted_ascii(base, length, result, result_length); + char* result; + int result_length; + if (!is_latin1) { + jchar* base = value->char_at_addr(0); + result_length = UNICODE::quoted_ascii_length(base, length) + 1; + result = NEW_RESOURCE_ARRAY(char, result_length); + UNICODE::as_quoted_ascii(base, length, result, result_length); + } else { + jbyte* base = value->byte_at_addr(0); + result_length = UNICODE::quoted_ascii_length(base, length) + 1; + result = NEW_RESOURCE_ARRAY(char, result_length); + UNICODE::as_quoted_ascii(base, length, result, result_length); + } assert(result_length >= length + 1, "must not be shorter"); assert(result_length == (int)strlen(result) + 1, "must match"); return result; @@ -370,89 +514,141 @@ char* java_lang_String::as_quoted_ascii(oop java_string) { unsigned int java_lang_String::hash_string(oop java_string) { int length = java_lang_String::length(java_string); - // Zero length string doesn't hash necessarily hash to zero. + // Zero length string doesn't necessarily hash to zero. if (length == 0) { - return StringTable::hash_string(NULL, 0); + return StringTable::hash_string((jchar*) NULL, 0); } typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); - return StringTable::hash_string(value->char_at_addr(offset), length); + bool is_latin1 = java_lang_String::is_latin1(java_string); + if (is_latin1) { + return StringTable::hash_string(value->byte_at_addr(0), length); + } else { + return StringTable::hash_string(value->char_at_addr(0), length); + } } Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) { oop obj = java_string(); typeArrayOop value = java_lang_String::value(obj); - int offset = java_lang_String::offset(obj); int length = java_lang_String::length(obj); - jchar* base = (length == 0) ? NULL : value->char_at_addr(offset); - Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD); - return sym; + bool is_latin1 = java_lang_String::is_latin1(obj); + if (!is_latin1) { + jchar* base = (length == 0) ? NULL : value->char_at_addr(0); + Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD); + return sym; + } else { + ResourceMark rm; + jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0); + const char* base = UNICODE::as_utf8(position, length); + Symbol* sym = SymbolTable::lookup(base, length, THREAD); + return sym; + } } Symbol* java_lang_String::as_symbol_or_null(oop java_string) { typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); - jchar* base = (length == 0) ? NULL : value->char_at_addr(offset); - return SymbolTable::probe_unicode(base, length); + bool is_latin1 = java_lang_String::is_latin1(java_string); + if (!is_latin1) { + jchar* base = (length == 0) ? NULL : value->char_at_addr(0); + return SymbolTable::probe_unicode(base, length); + } else { + ResourceMark rm; + jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0); + const char* base = UNICODE::as_utf8(position, length); + return SymbolTable::probe(base, length); + } } - int java_lang_String::utf8_length(oop java_string) { typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); - jchar* position = (length == 0) ? NULL : value->char_at_addr(offset); - return UNICODE::utf8_length(position, length); + bool is_latin1 = java_lang_String::is_latin1(java_string); + if (length == 0) { + return 0; + } + if (!is_latin1) { + return UNICODE::utf8_length(value->char_at_addr(0), length); + } else { + return UNICODE::utf8_length(value->byte_at_addr(0), length); + } } char* java_lang_String::as_utf8_string(oop java_string) { typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); - jchar* position = (length == 0) ? NULL : value->char_at_addr(offset); - return UNICODE::as_utf8(position, length); + bool is_latin1 = java_lang_String::is_latin1(java_string); + if (!is_latin1) { + jchar* position = (length == 0) ? NULL : value->char_at_addr(0); + return UNICODE::as_utf8(position, length); + } else { + jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0); + return UNICODE::as_utf8(position, length); + } } char* java_lang_String::as_utf8_string(oop java_string, char* buf, int buflen) { typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); - jchar* position = (length == 0) ? NULL : value->char_at_addr(offset); - return UNICODE::as_utf8(position, length, buf, buflen); + bool is_latin1 = java_lang_String::is_latin1(java_string); + if (!is_latin1) { + jchar* position = (length == 0) ? NULL : value->char_at_addr(0); + return UNICODE::as_utf8(position, length, buf, buflen); + } else { + jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0); + return UNICODE::as_utf8(position, length, buf, buflen); + } } char* java_lang_String::as_utf8_string(oop java_string, int start, int len) { typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); assert(start + len <= length, "just checking"); - jchar* position = value->char_at_addr(offset + start); - return UNICODE::as_utf8(position, len); + bool is_latin1 = java_lang_String::is_latin1(java_string); + if (!is_latin1) { + jchar* position = value->char_at_addr(start); + return UNICODE::as_utf8(position, len); + } else { + jbyte* position = value->byte_at_addr(start); + return UNICODE::as_utf8(position, len); + } } char* java_lang_String::as_utf8_string(oop java_string, int start, int len, char* buf, int buflen) { typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); assert(start + len <= length, "just checking"); - jchar* position = value->char_at_addr(offset + start); - return UNICODE::as_utf8(position, len, buf, buflen); + bool is_latin1 = java_lang_String::is_latin1(java_string); + if (!is_latin1) { + jchar* position = value->char_at_addr(start); + return UNICODE::as_utf8(position, len, buf, buflen); + } else { + jbyte* position = value->byte_at_addr(start); + return UNICODE::as_utf8(position, len, buf, buflen); + } } bool java_lang_String::equals(oop java_string, jchar* chars, int len) { assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string"); typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); if (length != len) { return false; } - for (int i = 0; i < len; i++) { - if (value->char_at(i + offset) != chars[i]) { - return false; + bool is_latin1 = java_lang_String::is_latin1(java_string); + if (!is_latin1) { + for (int i = 0; i < len; i++) { + if (value->char_at(i) != chars[i]) { + return false; + } + } + } else { + for (int i = 0; i < len; i++) { + if ((((jchar) value->byte_at(i)) & 0xff) != chars[i]) { + return false; + } } } return true; @@ -464,17 +660,20 @@ bool java_lang_String::equals(oop str1, oop str2) { assert(str2->klass() == SystemDictionary::String_klass(), "must be java String"); typeArrayOop value1 = java_lang_String::value(str1); - int offset1 = java_lang_String::offset(str1); int length1 = java_lang_String::length(str1); + bool is_latin1 = java_lang_String::is_latin1(str1); typeArrayOop value2 = java_lang_String::value(str2); - int offset2 = java_lang_String::offset(str2); int length2 = java_lang_String::length(str2); + bool is_latin2 = java_lang_String::is_latin1(str2); - if (length1 != length2) { + if ((length1 != length2) || (is_latin1 != is_latin2)) { + // Strings of different size or with different + // coders are never equal. return false; } - for (int i = 0; i < length1; i++) { - if (value1->char_at(i + offset1) != value2->char_at(i + offset2)) { + int blength1 = value1->length(); + for (int i = 0; i < value1->length(); i++) { + if (value1->byte_at(i) != value2->byte_at(i)) { return false; } } @@ -492,12 +691,13 @@ void java_lang_String::print(oop java_string, outputStream* st) { return; } - int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); + bool is_latin1 = java_lang_String::is_latin1(java_string); st->print("\""); for (int index = 0; index < length; index++) { - st->print("%c", value->char_at(index + offset)); + st->print("%c", (!is_latin1) ? value->char_at(index) : + ((jchar) value->byte_at(index)) & 0xff ); } st->print("\""); } @@ -555,7 +755,7 @@ void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) { // If the offset was read from the shared archive, it was fixed up already if (!k->is_shared()) { - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { // During bootstrap, java.lang.Class wasn't loaded so static field // offsets were computed without the size added it. Go back and // update all the static field offsets to included the size. @@ -613,13 +813,13 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror())); // It might also have a component mirror. This mirror must already exist. - if (k->oop_is_array()) { + if (k->is_array_klass()) { Handle comp_mirror; - if (k->oop_is_typeArray()) { + if (k->is_typeArray_klass()) { BasicType type = TypeArrayKlass::cast(k())->element_type(); comp_mirror = Universe::java_mirror(type); } else { - assert(k->oop_is_objArray(), "Must be"); + assert(k->is_objArray_klass(), "Must be"); Klass* element_klass = ObjArrayKlass::cast(k())->element_klass(); assert(element_klass != NULL, "Must have an element klass"); comp_mirror = element_klass->java_mirror(); @@ -631,7 +831,7 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader, set_component_mirror(mirror(), comp_mirror()); set_array_klass(comp_mirror(), k()); } else { - assert(k->oop_is_instance(), "Must be"); + assert(k->is_instance_klass(), "Must be"); initialize_mirror_fields(k, mirror, protection_domain, THREAD); if (HAS_PENDING_EXCEPTION) { @@ -770,7 +970,7 @@ void java_lang_Class::print_signature(oop java_class, outputStream* st) { name = vmSymbols::type_signature(primitive_type(java_class)); } else { Klass* k = as_Klass(java_class); - is_instance = k->oop_is_instance(); + is_instance = k->is_instance_klass(); name = k->name(); } if (name == NULL) { @@ -793,7 +993,7 @@ Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, name->increment_refcount(); } else { Klass* k = as_Klass(java_class); - if (!k->oop_is_instance()) { + if (!k->is_instance_klass()) { name = k->name(); name->increment_refcount(); } else { @@ -829,13 +1029,13 @@ const char* java_lang_Class::as_external_name(oop java_class) { Klass* java_lang_Class::array_klass(oop java_class) { Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset)); - assert(k == NULL || k->is_klass() && k->oop_is_array(), "should be array klass"); + assert(k == NULL || k->is_klass() && k->is_array_klass(), "should be array klass"); return k; } void java_lang_Class::set_array_klass(oop java_class, Klass* klass) { - assert(klass->is_klass() && klass->oop_is_array(), "should be array klass"); + assert(klass->is_klass() && klass->is_array_klass(), "should be array klass"); java_class->metadata_field_put(_array_klass_offset, klass); } @@ -1169,10 +1369,13 @@ oop java_lang_ThreadGroup::parent(oop java_thread_group) { // ("name as oop" accessor is not necessary) -typeArrayOop java_lang_ThreadGroup::name(oop java_thread_group) { +const char* java_lang_ThreadGroup::name(oop java_thread_group) { oop name = java_thread_group->obj_field(_name_offset); // ThreadGroup.name can be null - return name == NULL ? (typeArrayOop)NULL : java_lang_String::value(name); + if (name != NULL) { + return java_lang_String::as_utf8_string(name); + } + return NULL; } int java_lang_ThreadGroup::nthreads(oop java_thread_group) { @@ -1236,7 +1439,7 @@ void java_lang_ThreadGroup::compute_offsets() { } oop java_lang_Throwable::unassigned_stacktrace() { - InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::Throwable_klass()); + InstanceKlass* ik = SystemDictionary::Throwable_klass(); address addr = ik->static_field_addr(static_unassigned_stacktrace_offset); if (UseCompressedOops) { return oopDesc::load_decode_heap_oop((narrowOop *)addr); @@ -1293,7 +1496,7 @@ void java_lang_Throwable::print(oop throwable, outputStream* st) { ResourceMark rm; Klass* k = throwable->klass(); assert(k != NULL, "just checking"); - st->print("%s", InstanceKlass::cast(k)->external_name()); + st->print("%s", k->external_name()); oop msg = message(throwable); if (msg != NULL) { st->print(": %s", java_lang_String::as_utf8_string(msg)); @@ -1305,7 +1508,7 @@ void java_lang_Throwable::print(Handle throwable, outputStream* st) { ResourceMark rm; Klass* k = throwable->klass(); assert(k != NULL, "just checking"); - st->print("%s", InstanceKlass::cast(k)->external_name()); + st->print("%s", k->external_name()); oop msg = message(throwable); if (msg != NULL) { st->print(": %s", java_lang_String::as_utf8_string(msg)); @@ -1561,7 +1764,7 @@ void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, st->print_cr("%s", buf); } -void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) { +void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) { Handle mirror = method->method_holder()->java_mirror(); int method_id = method->orig_method_idnum(); int version = method->constants()->version(); @@ -1632,7 +1835,7 @@ void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) { } } -void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS) { +void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHandle& method, TRAPS) { if (!StackTraceInThrowable) return; ResourceMark rm(THREAD); @@ -1763,7 +1966,7 @@ void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle met set_backtrace(throwable(), bt.backtrace()); } -void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method) { +void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHandle& method) { // No-op if stack trace is disabled if (!StackTraceInThrowable) { return; @@ -1945,7 +2148,7 @@ oop java_lang_StackTraceElement::create(Handle mirror, int method_id, return element(); } -oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { +oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { Handle mirror (THREAD, method->method_holder()->java_mirror()); int method_id = method->orig_method_idnum(); int cpref = method->name_index(); @@ -2506,7 +2709,7 @@ ConstantPool* sun_reflect_ConstantPool::get_cp(oop reflect) { oop mirror = reflect->obj_field(_oop_offset); Klass* k = java_lang_Class::as_Klass(mirror); - assert(k->oop_is_instance(), "Must be"); + assert(k->is_instance_klass(), "Must be"); // Get the constant pool back from the klass. Since class redefinition // merges the new constant pool into the old, this is essentially the @@ -2663,13 +2866,13 @@ void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream* // Support for java_lang_ref_Reference HeapWord *java_lang_ref_Reference::pending_list_lock_addr() { - InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::Reference_klass()); + InstanceKlass* ik = SystemDictionary::Reference_klass(); address addr = ik->static_field_addr(static_lock_offset); return (HeapWord*) addr; } oop java_lang_ref_Reference::pending_list_lock() { - InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::Reference_klass()); + InstanceKlass* ik = SystemDictionary::Reference_klass(); address addr = ik->static_field_addr(static_lock_offset); if (UseCompressedOops) { return oopDesc::load_decode_heap_oop((narrowOop *)addr); @@ -2679,7 +2882,7 @@ oop java_lang_ref_Reference::pending_list_lock() { } HeapWord *java_lang_ref_Reference::pending_list_addr() { - InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::Reference_klass()); + InstanceKlass* ik = SystemDictionary::Reference_klass(); address addr = ik->static_field_addr(static_pending_offset); // XXX This might not be HeapWord aligned, almost rather be char *. return (HeapWord*)addr; @@ -2702,13 +2905,13 @@ jlong java_lang_ref_SoftReference::timestamp(oop ref) { } jlong java_lang_ref_SoftReference::clock() { - InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::SoftReference_klass()); + InstanceKlass* ik = SystemDictionary::SoftReference_klass(); jlong* offset = (jlong*)ik->static_field_addr(static_clock_offset); return *offset; } void java_lang_ref_SoftReference::set_clock(jlong value) { - InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::SoftReference_klass()); + InstanceKlass* ik = SystemDictionary::SoftReference_klass(); jlong* offset = (jlong*)ik->static_field_addr(static_clock_offset); *offset = value; } @@ -3033,7 +3236,7 @@ int java_security_AccessControlContext::_isAuthorized_offset = -1; void java_security_AccessControlContext::compute_offsets() { assert(_isPrivileged_offset == 0, "offsets should be initialized only once"); fieldDescriptor fd; - InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::AccessControlContext_klass()); + InstanceKlass* ik = SystemDictionary::AccessControlContext_klass(); if (!ik->find_local_field(vmSymbols::context_name(), vmSymbols::protectiondomain_signature(), &fd)) { fatal("Invalid layout of java.security.AccessControlContext"); @@ -3066,9 +3269,9 @@ bool java_security_AccessControlContext::is_authorized(Handle context) { oop java_security_AccessControlContext::create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS) { assert(_isPrivileged_offset != 0, "offsets should have been initialized"); // Ensure klass is initialized - InstanceKlass::cast(SystemDictionary::AccessControlContext_klass())->initialize(CHECK_0); + SystemDictionary::AccessControlContext_klass()->initialize(CHECK_0); // Allocate result - oop result = InstanceKlass::cast(SystemDictionary::AccessControlContext_klass())->allocate_instance(CHECK_0); + oop result = SystemDictionary::AccessControlContext_klass()->allocate_instance(CHECK_0); // Fill in values result->obj_field_put(_context_offset, context()); result->obj_field_put(_privilegedContext_offset, privileged_context()); @@ -3190,7 +3393,7 @@ int java_lang_System::err_offset_in_bytes() { bool java_lang_System::has_security_manager() { - InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::System_klass()); + InstanceKlass* ik = SystemDictionary::System_klass(); address addr = ik->static_field_addr(static_security_offset); if (UseCompressedOops) { return oopDesc::load_decode_heap_oop((narrowOop *)addr) != NULL; @@ -3541,14 +3744,13 @@ void JavaClasses::check_offsets() { // java.lang.String - CHECK_OFFSET("java/lang/String", java_lang_String, value, "[C"); - if (java_lang_String::has_offset_field()) { - CHECK_OFFSET("java/lang/String", java_lang_String, offset, "I"); - CHECK_OFFSET("java/lang/String", java_lang_String, count, "I"); - } + CHECK_OFFSET("java/lang/String", java_lang_String, value, "[B"); if (java_lang_String::has_hash_field()) { CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I"); } + if (java_lang_String::has_coder_field()) { + CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B"); + } // java.lang.Class @@ -3630,8 +3832,8 @@ void JavaClasses::check_offsets() { #endif // PRODUCT int InjectedField::compute_offset() { - Klass* klass_oop = klass(); - for (AllFieldStream fs(InstanceKlass::cast(klass_oop)); !fs.done(); fs.next()) { + InstanceKlass* ik = InstanceKlass::cast(klass()); + for (AllFieldStream fs(ik); !fs.done(); fs.next()) { if (!may_be_java && !fs.access_flags().is_internal()) { // Only look at injected fields continue; @@ -3641,11 +3843,11 @@ int InjectedField::compute_offset() { } } ResourceMark rm; - tty->print_cr("Invalid layout of %s at %s/%s%s", InstanceKlass::cast(klass_oop)->external_name(), name()->as_C_string(), signature()->as_C_string(), may_be_java ? " (may_be_java)" : ""); + tty->print_cr("Invalid layout of %s at %s/%s%s", ik->external_name(), name()->as_C_string(), signature()->as_C_string(), may_be_java ? " (may_be_java)" : ""); #ifndef PRODUCT - klass_oop->print(); + ik->print(); tty->print_cr("all fields:"); - for (AllFieldStream fs(InstanceKlass::cast(klass_oop)); !fs.done(); fs.next()) { + for (AllFieldStream fs(ik); !fs.done(); fs.next()) { tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); } #endif //PRODUCT diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 4199d350bee..403e33e9ee3 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -53,28 +53,28 @@ class java_lang_String : AllStatic { private: static int value_offset; - static int offset_offset; - static int count_offset; static int hash_offset; + static int coder_offset; static bool initialized; - static Handle basic_create(int length, TRAPS); + static Handle basic_create(int length, bool byte_arr, TRAPS); - static void set_offset(oop string, int offset) { + static void set_coder(oop string, jbyte coder) { assert(initialized, "Must be initialized"); - if (offset_offset > 0) { - string->int_field_put(offset_offset, offset); - } - } - static void set_count( oop string, int count) { - assert(initialized, "Must be initialized"); - if (count_offset > 0) { - string->int_field_put(count_offset, count); + if (coder_offset > 0) { + string->byte_field_put(coder_offset, coder); } } public: + + // Coders + enum Coder { + CODER_LATIN1 = 0, + CODER_UTF16 = 1 + }; + static void compute_offsets(); // Instance creation @@ -86,37 +86,29 @@ class java_lang_String : AllStatic { static Handle create_from_platform_dependent_str(const char* str, TRAPS); static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS); - static bool has_offset_field() { - assert(initialized, "Must be initialized"); - return (offset_offset > 0); - } - - static bool has_count_field() { - assert(initialized, "Must be initialized"); - return (count_offset > 0); - } - static bool has_hash_field() { assert(initialized, "Must be initialized"); return (hash_offset > 0); } + static bool has_coder_field() { + assert(initialized, "Must be initialized"); + return (coder_offset > 0); + } + + static void set_compact_strings(bool value); static int value_offset_in_bytes() { assert(initialized && (value_offset > 0), "Must be initialized"); return value_offset; } - static int count_offset_in_bytes() { - assert(initialized && (count_offset > 0), "Must be initialized"); - return count_offset; - } - static int offset_offset_in_bytes() { - assert(initialized && (offset_offset > 0), "Must be initialized"); - return offset_offset; - } static int hash_offset_in_bytes() { assert(initialized && (hash_offset > 0), "Must be initialized"); return hash_offset; } + static int coder_offset_in_bytes() { + assert(initialized && (coder_offset > 0), "Must be initialized"); + return coder_offset; + } static void set_value_raw(oop string, typeArrayOop buffer) { assert(initialized, "Must be initialized"); @@ -142,28 +134,30 @@ class java_lang_String : AllStatic { assert(is_instance(java_string), "must be java_string"); return java_string->int_field(hash_offset); } - static int offset(oop java_string) { + static bool is_latin1(oop java_string) { assert(initialized, "Must be initialized"); assert(is_instance(java_string), "must be java_string"); - if (offset_offset > 0) { - return java_string->int_field(offset_offset); + if (coder_offset > 0) { + jbyte coder = java_string->byte_field(coder_offset); + assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings"); + return coder == CODER_LATIN1; } else { - return 0; + return false; } } static int length(oop java_string) { assert(initialized, "Must be initialized"); assert(is_instance(java_string), "must be java_string"); - if (count_offset > 0) { - return java_string->int_field(count_offset); - } else { - typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset)); - if (value_array == NULL) { - return 0; - } else { - return value_array->length(); - } + typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset)); + if (value_array == NULL) { + return 0; } + int arr_length = value_array->length(); + if (!is_latin1(java_string)) { + assert((arr_length & 1) == 0, "should be even for UTF16 string"); + arr_length >>= 1; // convert number of bytes to number of elements + } + return arr_length; } static int utf8_length(oop java_string); @@ -187,7 +181,7 @@ class java_lang_String : AllStatic { // hash P(31) from Kernighan & Ritchie // // For this reason, THIS ALGORITHM MUST MATCH String.hashCode(). - template static unsigned int hash_code(T* s, int len) { + static unsigned int hash_code(const jchar* s, int len) { unsigned int h = 0; while (len-- > 0) { h = 31*h + (unsigned int) *s; @@ -195,7 +189,18 @@ class java_lang_String : AllStatic { } return h; } + + static unsigned int hash_code(const jbyte* s, int len) { + unsigned int h = 0; + while (len-- > 0) { + h = 31*h + (((unsigned int) *s) & 0xFF); + s++; + } + return h; + } + static unsigned int hash_code(oop java_string); + static unsigned int latin1_hash_code(typeArrayOop value, int len); // This is the string hash code used by the StringTable, which may be // the same as String.hashCode or an alternate hash code. @@ -451,7 +456,7 @@ class java_lang_ThreadGroup : AllStatic { // parent ThreadGroup static oop parent(oop java_thread_group); // name - static typeArrayOop name(oop java_thread_group); + static const char* name(oop java_thread_group); // ("name as oop" accessor is not necessary) // Number of threads in group static int nthreads(oop java_thread_group); @@ -532,7 +537,7 @@ class java_lang_Throwable: AllStatic { static Symbol* detail_message(oop throwable); static void print_stack_element(outputStream *st, Handle mirror, int method, int version, int bci, int cpref); - static void print_stack_element(outputStream *st, methodHandle method, int bci); + static void print_stack_element(outputStream *st, const methodHandle& method, int bci); static void print_stack_usage(Handle stream); // Allocate space for backtrace (created but stack trace not filled in) @@ -540,8 +545,8 @@ class java_lang_Throwable: AllStatic { // Fill in current stack trace for throwable with preallocated backtrace (no GC) static void fill_in_stack_trace_of_preallocated_backtrace(Handle throwable); // Fill in current stack trace, can cause GC - static void fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS); - static void fill_in_stack_trace(Handle throwable, methodHandle method = methodHandle()); + static void fill_in_stack_trace(Handle throwable, const methodHandle& method, TRAPS); + static void fill_in_stack_trace(Handle throwable, const methodHandle& method = methodHandle()); // Programmatic access to stack trace static oop get_stack_trace_element(oop throwable, int index, TRAPS); static int get_stack_trace_depth(oop throwable, TRAPS); @@ -1347,7 +1352,7 @@ class java_lang_StackTraceElement: AllStatic { // Create an instance of StackTraceElement static oop create(Handle mirror, int method, int version, int bci, int cpref, TRAPS); - static oop create(methodHandle method, int bci, TRAPS); + static oop create(const methodHandle& method, int bci, TRAPS); // Debugging friend class JavaClasses; diff --git a/hotspot/src/share/vm/classfile/loaderConstraints.cpp b/hotspot/src/share/vm/classfile/loaderConstraints.cpp index 1cdc34d0548..5780bad832e 100644 --- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp +++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -320,7 +320,7 @@ Klass* LoaderConstraintTable::find_constrained_klass(Symbol* name, Handle loader) { LoaderConstraintEntry *p = *(find_loader_constraint(name, loader)); if (p != NULL && p->klass() != NULL) { - if (p->klass()->oop_is_instance() && !InstanceKlass::cast(p->klass())->is_loaded()) { + if (p->klass()->is_instance_klass() && !InstanceKlass::cast(p->klass())->is_loaded()) { // Only return fully loaded classes. Classes found through the // constraints might still be in the process of loading. return NULL; diff --git a/hotspot/src/share/vm/classfile/placeholders.cpp b/hotspot/src/share/vm/classfile/placeholders.cpp index 10d7650db58..22f1ad861f0 100644 --- a/hotspot/src/share/vm/classfile/placeholders.cpp +++ b/hotspot/src/share/vm/classfile/placeholders.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -244,7 +244,7 @@ void PlaceholderEntry::verify() const { guarantee(loader_data()->class_loader() == NULL || loader_data()->class_loader()->is_instance(), "checking type of _loader"); guarantee(instance_klass() == NULL - || instance_klass()->oop_is_instance(), + || instance_klass()->is_instance_klass(), "checking type of instance_klass result"); } diff --git a/hotspot/src/share/vm/classfile/placeholders.hpp b/hotspot/src/share/vm/classfile/placeholders.hpp index ca0d85af0fb..f5fc9b40845 100644 --- a/hotspot/src/share/vm/classfile/placeholders.hpp +++ b/hotspot/src/share/vm/classfile/placeholders.hpp @@ -220,7 +220,7 @@ class PlaceholderEntry : public HashtableEntry { } SeenThread* actionToQueue(PlaceholderTable::classloadAction action) { - SeenThread* queuehead; + SeenThread* queuehead = NULL; switch (action) { case PlaceholderTable::LOAD_INSTANCE: queuehead = _loadInstanceThreadQ; diff --git a/hotspot/src/share/vm/classfile/resolutionErrors.cpp b/hotspot/src/share/vm/classfile/resolutionErrors.cpp index cef42b1888d..d2e11743c2e 100644 --- a/hotspot/src/share/vm/classfile/resolutionErrors.cpp +++ b/hotspot/src/share/vm/classfile/resolutionErrors.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ // add new entry to the table void ResolutionErrorTable::add_entry(int index, unsigned int hash, - constantPoolHandle pool, int cp_index, + const constantPoolHandle& pool, int cp_index, Symbol* error, Symbol* message) { assert_locked_or_safepoint(SystemDictionary_lock); @@ -44,7 +44,7 @@ void ResolutionErrorTable::add_entry(int index, unsigned int hash, // find entry in the table ResolutionErrorEntry* ResolutionErrorTable::find_entry(int index, unsigned int hash, - constantPoolHandle pool, int cp_index) + const constantPoolHandle& pool, int cp_index) { assert_locked_or_safepoint(SystemDictionary_lock); diff --git a/hotspot/src/share/vm/classfile/resolutionErrors.hpp b/hotspot/src/share/vm/classfile/resolutionErrors.hpp index c9e76827cb4..866a4b122a3 100644 --- a/hotspot/src/share/vm/classfile/resolutionErrors.hpp +++ b/hotspot/src/share/vm/classfile/resolutionErrors.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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 @@ -56,15 +56,15 @@ public: } void add_entry(int index, unsigned int hash, - constantPoolHandle pool, int which, Symbol* error, Symbol* message); + const constantPoolHandle& pool, int which, Symbol* error, Symbol* message); // find error given the constant pool and constant pool index ResolutionErrorEntry* find_entry(int index, unsigned int hash, - constantPoolHandle pool, int cp_index); + const constantPoolHandle& pool, int cp_index); - unsigned int compute_hash(constantPoolHandle pool, int cp_index) { + unsigned int compute_hash(const constantPoolHandle& pool, int cp_index) { return (unsigned int) pool->identity_hash() + cp_index; } diff --git a/hotspot/src/share/vm/classfile/stringTable.cpp b/hotspot/src/share/vm/classfile/stringTable.cpp index c14cd9e036a..7298d848097 100644 --- a/hotspot/src/share/vm/classfile/stringTable.cpp +++ b/hotspot/src/share/vm/classfile/stringTable.cpp @@ -94,11 +94,16 @@ volatile int StringTable::_parallel_claimed_idx = 0; CompactHashtable StringTable::_shared_table; // Pick hashing algorithm -unsigned int StringTable::hash_string(const jchar* s, int len) { +template +unsigned int StringTable::hash_string(const T* s, int len) { return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) : java_lang_String::hash_code(s, len); } +// Explicit instantiation for all supported types. +template unsigned int StringTable::hash_string(const jchar* s, int len); +template unsigned int StringTable::hash_string(const jbyte* s, int len); + oop StringTable::lookup_shared(jchar* name, int len) { // java_lang_String::hash_code() was used to compute hash values in the shared table. Don't // use the hash value from StringTable::hash_string() as it might use alternate hashcode. @@ -409,17 +414,25 @@ void StringTable::dump(outputStream* st, bool verbose) { for ( ; p != NULL; p = p->next()) { oop s = p->literal(); typeArrayOop value = java_lang_String::value(s); - int offset = java_lang_String::offset(s); int length = java_lang_String::length(s); + bool is_latin1 = java_lang_String::is_latin1(s); if (length <= 0) { st->print("%d: ", length); } else { ResourceMark rm(THREAD); - jchar* chars = (jchar*)value->char_at_addr(offset); - int utf8_length = UNICODE::utf8_length(chars, length); - char* utf8_string = NEW_RESOURCE_ARRAY(char, utf8_length + 1); - UNICODE::convert_to_utf8(chars, length, utf8_string); + int utf8_length; + char* utf8_string; + + if (!is_latin1) { + jchar* chars = value->char_at_addr(0); + utf8_length = UNICODE::utf8_length(chars, length); + utf8_string = UNICODE::as_utf8(chars, length); + } else { + jbyte* bytes = value->byte_at_addr(0); + utf8_length = UNICODE::utf8_length(bytes, length); + utf8_string = UNICODE::as_utf8(bytes, length); + } st->print("%d: ", utf8_length); HashtableTextDump::put_utf8(st, utf8_string, utf8_length); diff --git a/hotspot/src/share/vm/classfile/stringTable.hpp b/hotspot/src/share/vm/classfile/stringTable.hpp index e5b9e2b6cfc..f7dc5967dfc 100644 --- a/hotspot/src/share/vm/classfile/stringTable.hpp +++ b/hotspot/src/share/vm/classfile/stringTable.hpp @@ -111,7 +111,7 @@ public: // Hashing algorithm, used as the hash value used by the // StringTable for bucket selection and comparison (stored in the // HashtableEntry structures). This is used in the String.intern() method. - static unsigned int hash_string(const jchar* s, int len); + template static unsigned int hash_string(const T* s, int len); // Internal test. static void test_alt_hash() PRODUCT_RETURN; diff --git a/hotspot/src/share/vm/classfile/symbolTable.cpp b/hotspot/src/share/vm/classfile/symbolTable.cpp index b5c3a157e12..eeb23890265 100644 --- a/hotspot/src/share/vm/classfile/symbolTable.cpp +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp @@ -244,7 +244,7 @@ Symbol* SymbolTable::lookup(int index, const char* name, unsigned int SymbolTable::hash_symbol(const char* s, int len) { return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), (const jbyte*)s, len) : - java_lang_String::hash_code(s, len); + java_lang_String::hash_code((const jbyte*)s, len); } @@ -371,7 +371,7 @@ Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, } } -void SymbolTable::add(ClassLoaderData* loader_data, constantPoolHandle cp, +void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp, int names_count, const char** names, int* lengths, int* cp_indices, unsigned int* hashValues, TRAPS) { @@ -452,7 +452,7 @@ Symbol* SymbolTable::basic_add(int index_arg, u1 *name, int len, // This version of basic_add adds symbols in batch from the constant pool // parsing. -bool SymbolTable::basic_add(ClassLoaderData* loader_data, constantPoolHandle cp, +bool SymbolTable::basic_add(ClassLoaderData* loader_data, const constantPoolHandle& cp, int names_count, const char** names, int* lengths, int* cp_indices, unsigned int* hashValues, diff --git a/hotspot/src/share/vm/classfile/symbolTable.hpp b/hotspot/src/share/vm/classfile/symbolTable.hpp index 4095e6e7615..29ee8d2b779 100644 --- a/hotspot/src/share/vm/classfile/symbolTable.hpp +++ b/hotspot/src/share/vm/classfile/symbolTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -100,12 +100,12 @@ private: Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue, bool c_heap, TRAPS); bool basic_add(ClassLoaderData* loader_data, - constantPoolHandle cp, int names_count, + const constantPoolHandle& cp, int names_count, const char** names, int* lengths, int* cp_indices, unsigned int* hashValues, TRAPS); static void new_symbols(ClassLoaderData* loader_data, - constantPoolHandle cp, int names_count, + const constantPoolHandle& cp, int names_count, const char** name, int* lengths, int* cp_indices, unsigned int* hashValues, TRAPS) { @@ -165,12 +165,12 @@ public: // Look up the address of the literal in the SymbolTable for this Symbol* static Symbol** lookup_symbol_addr(Symbol* sym); - // jchar (utf16) version of lookups + // jchar (UTF16) version of lookups static Symbol* lookup_unicode(const jchar* name, int len, TRAPS); static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash); static void add(ClassLoaderData* loader_data, - constantPoolHandle cp, int names_count, + const constantPoolHandle& cp, int names_count, const char** names, int* lengths, int* cp_indices, unsigned int* hashValues, TRAPS); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index bfae05db988..ec634070767 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -88,10 +88,10 @@ const int SystemDictionary::_primelist[_prime_array_size] = {1009,2017,4049,50 oop SystemDictionary::_system_loader_lock_obj = NULL; -Klass* SystemDictionary::_well_known_klasses[SystemDictionary::WKID_LIMIT] +InstanceKlass* SystemDictionary::_well_known_klasses[SystemDictionary::WKID_LIMIT] = { NULL /*, NULL...*/ }; -Klass* SystemDictionary::_box_klasses[T_VOID+1] = { NULL /*, NULL...*/ }; +InstanceKlass* SystemDictionary::_box_klasses[T_VOID+1] = { NULL /*, NULL...*/ }; oop SystemDictionary::_java_system_loader = NULL; @@ -99,7 +99,7 @@ bool SystemDictionary::_has_loadClassInternal = false; bool SystemDictionary::_has_checkPackageAccess = false; // lazily initialized klass variables -Klass* volatile SystemDictionary::_abstract_ownable_synchronizer_klass = NULL; +InstanceKlass* volatile SystemDictionary::_abstract_ownable_synchronizer_klass = NULL; // ---------------------------------------------------------------------------- @@ -357,7 +357,7 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name, // so we don't throw an exception here. // see: nsk redefclass014 & java.lang.instrument Instrument032 if ((childk != NULL ) && (is_superclass) && - ((quicksuperk = InstanceKlass::cast(childk)->super()) != NULL) && + ((quicksuperk = childk->super()) != NULL) && ((quicksuperk->name() == class_name) && (quicksuperk->class_loader() == class_loader()))) { @@ -1257,8 +1257,7 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, } // notify a class loaded from shared object - ClassLoadingService::notify_class_loaded(InstanceKlass::cast(ik()), - true /* shared class */); + ClassLoadingService::notify_class_loaded(ik(), true /* shared class */); } return ik; } @@ -1805,7 +1804,7 @@ void SystemDictionary::load_abstract_ownable_synchronizer_klass(TRAPS) { Klass* k = resolve_or_fail(vmSymbols::java_util_concurrent_locks_AbstractOwnableSynchronizer(), true, CHECK); // Force a fence to prevent any read before the write completes OrderAccess::fence(); - _abstract_ownable_synchronizer_klass = k; + _abstract_ownable_synchronizer_klass = InstanceKlass::cast(k); } } @@ -1846,14 +1845,16 @@ bool SystemDictionary::initialize_wk_klass(WKID id, int init_opt, TRAPS) { int info = wk_init_info[id - FIRST_WKID]; int sid = (info >> CEIL_LG_OPTION_LIMIT); Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid); - Klass** klassp = &_well_known_klasses[id]; + InstanceKlass** klassp = &_well_known_klasses[id]; bool must_load = (init_opt < SystemDictionary::Opt); if ((*klassp) == NULL) { + Klass* k; if (must_load) { - (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class + k = resolve_or_fail(symbol, true, CHECK_0); // load required class } else { - (*klassp) = resolve_or_null(symbol, CHECK_0); // load optional klass + k = resolve_or_null(symbol, CHECK_0); // load optional klass } + (*klassp) = (k == NULL) ? NULL : InstanceKlass::cast(k); } return ((*klassp) != NULL); } @@ -1966,7 +1967,8 @@ void SystemDictionary::check_constraints(int d_index, unsigned int d_hash, instanceKlassHandle k, Handle class_loader, bool defining, TRAPS) { - const char *linkage_error = NULL; + const char *linkage_error1 = NULL; + const char *linkage_error2 = NULL; { Symbol* name = k->name(); ClassLoaderData *loader_data = class_loader_data(class_loader); @@ -1981,10 +1983,10 @@ void SystemDictionary::check_constraints(int d_index, unsigned int d_hash, // system dictionary only holds instance classes, placeholders // also holds array classes - assert(check->oop_is_instance(), "noninstance in systemdictionary"); + assert(check->is_instance_klass(), "noninstance in systemdictionary"); if ((defining == true) || (k() != check)) { - linkage_error = "loader (instance of %s): attempted duplicate class " - "definition for name: \"%s\""; + linkage_error1 = "loader (instance of "; + linkage_error2 = "): attempted duplicate class definition for name: \""; } else { return; } @@ -1995,10 +1997,10 @@ void SystemDictionary::check_constraints(int d_index, unsigned int d_hash, assert(ph_check == NULL || ph_check == name, "invalid symbol"); #endif - if (linkage_error == NULL) { + if (linkage_error1 == NULL) { if (constraints()->check_or_update(k, class_loader, name) == false) { - linkage_error = "loader constraint violation: loader (instance of %s)" - " previously initiated loading for a different type with name \"%s\""; + linkage_error1 = "loader constraint violation: loader (instance of "; + linkage_error2 = ") previously initiated loading for a different type with name \""; } } } @@ -2006,14 +2008,14 @@ void SystemDictionary::check_constraints(int d_index, unsigned int d_hash, // Throw error now if needed (cannot throw while holding // SystemDictionary_lock because of rank ordering) - if (linkage_error) { + if (linkage_error1) { ResourceMark rm(THREAD); const char* class_loader_name = loader_name(class_loader()); char* type_name = k->name()->as_C_string(); - size_t buflen = strlen(linkage_error) + strlen(class_loader_name) + - strlen(type_name); + size_t buflen = strlen(linkage_error1) + strlen(class_loader_name) + + strlen(linkage_error2) + strlen(type_name) + 2; // +2 for '"' and null byte. char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); - jio_snprintf(buf, buflen, linkage_error, class_loader_name, type_name); + jio_snprintf(buf, buflen, "%s%s%s%s\"", linkage_error1, class_loader_name, linkage_error2, type_name); THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); } } @@ -2155,7 +2157,7 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name, // Add entry to resolution error table to record the error when the first // attempt to resolve a reference to a class has failed. -void SystemDictionary::add_resolution_error(constantPoolHandle pool, int which, +void SystemDictionary::add_resolution_error(const constantPoolHandle& pool, int which, Symbol* error, Symbol* message) { unsigned int hash = resolution_errors()->compute_hash(pool, which); int index = resolution_errors()->hash_to_index(hash); @@ -2171,7 +2173,7 @@ void SystemDictionary::delete_resolution_error(ConstantPool* pool) { } // Lookup resolution error table. Returns error if found, otherwise NULL. -Symbol* SystemDictionary::find_resolution_error(constantPoolHandle pool, int which, +Symbol* SystemDictionary::find_resolution_error(const constantPoolHandle& pool, int which, Symbol** message) { unsigned int hash = resolution_errors()->compute_hash(pool, which); int index = resolution_errors()->hash_to_index(hash); @@ -2387,13 +2389,13 @@ methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name, // Out of an abundance of caution, we do not include any other classes, not even for packages like java.util. static bool is_always_visible_class(oop mirror) { Klass* klass = java_lang_Class::as_Klass(mirror); - if (klass->oop_is_objArray()) { + if (klass->is_objArray_klass()) { klass = ObjArrayKlass::cast(klass)->bottom_klass(); // check element type } - if (klass->oop_is_typeArray()) { + if (klass->is_typeArray_klass()) { return true; // primitive array } - assert(klass->oop_is_instance(), "%s", klass->external_name()); + assert(klass->is_instance_klass(), "%s", klass->external_name()); return klass->is_public() && (InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::Object_klass()) || // java.lang InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::MethodHandle_klass())); // java.lang.invoke @@ -2457,9 +2459,9 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature, Klass* sel_klass = java_lang_Class::as_Klass(mirror); mirror = NULL; // safety // Emulate ConstantPool::verify_constant_pool_resolve. - if (sel_klass->oop_is_objArray()) + if (sel_klass->is_objArray_klass()) sel_klass = ObjArrayKlass::cast(sel_klass)->bottom_klass(); - if (sel_klass->oop_is_instance()) { + if (sel_klass->is_instance_klass()) { KlassHandle sel_kh(THREAD, sel_klass); LinkResolver::check_klass_accessability(accessing_klass, sel_kh, CHECK_(empty)); } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 4eb39c59e9b..b9491903cfd 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -168,7 +168,7 @@ class Ticks; \ do_klass(StringBuffer_klass, java_lang_StringBuffer, Pre ) \ do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \ - do_klass(misc_Unsafe_klass, sun_misc_Unsafe, Pre ) \ + do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \ \ /* support for CDS */ \ do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream, Pre ) \ @@ -403,15 +403,15 @@ public: static void initialize(TRAPS); // Fast access to commonly used classes (preloaded) - static Klass* check_klass(Klass* k) { + static InstanceKlass* check_klass(InstanceKlass* k) { assert(k != NULL, "preloaded klass not initialized"); return k; } - static Klass* check_klass_Pre( Klass* k) { return check_klass(k); } - static Klass* check_klass_Opt( Klass* k) { return k; } + static InstanceKlass* check_klass_Pre(InstanceKlass* k) { return check_klass(k); } + static InstanceKlass* check_klass_Opt(InstanceKlass* k) { return k; } - JVMCI_ONLY(static Klass* check_klass_Jvmci(Klass* k) { return k; }) + JVMCI_ONLY(static InstanceKlass* check_klass_Jvmci(InstanceKlass* k) { return k; }) static bool initialize_wk_klass(WKID id, int init_opt, TRAPS); static void initialize_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS); @@ -422,19 +422,19 @@ public: public: #define WK_KLASS_DECLARE(name, symbol, option) \ - static Klass* name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \ - static Klass** name##_addr() { \ + static InstanceKlass* name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \ + static InstanceKlass** name##_addr() { \ return &SystemDictionary::_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \ } WK_KLASSES_DO(WK_KLASS_DECLARE); #undef WK_KLASS_DECLARE - static Klass* well_known_klass(WKID id) { + static InstanceKlass* well_known_klass(WKID id) { assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob"); return _well_known_klasses[id]; } - static Klass** well_known_klass_addr(WKID id) { + static InstanceKlass** well_known_klass_addr(WKID id) { assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob"); return &_well_known_klasses[id]; } @@ -442,7 +442,7 @@ public: // Local definition for direct access to the private array: #define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] - static Klass* box_klass(BasicType t) { + static InstanceKlass* box_klass(BasicType t) { assert((uint)t < T_VOID+1, "range check"); return check_klass(_box_klasses[t]); } @@ -450,7 +450,7 @@ public: // methods returning lazily loaded klasses // The corresponding method to load the class must be called before calling them. - static Klass* abstract_ownable_synchronizer_klass() { return check_klass(_abstract_ownable_synchronizer_klass); } + static InstanceKlass* abstract_ownable_synchronizer_klass() { return check_klass(_abstract_ownable_synchronizer_klass); } static void load_abstract_ownable_synchronizer_klass(TRAPS); @@ -547,10 +547,10 @@ public: // Record the error when the first attempt to resolve a reference from a constant // pool entry to a class fails. - static void add_resolution_error(constantPoolHandle pool, int which, Symbol* error, + static void add_resolution_error(const constantPoolHandle& pool, int which, Symbol* error, Symbol* message); static void delete_resolution_error(ConstantPool* pool); - static Symbol* find_resolution_error(constantPoolHandle pool, int which, + static Symbol* find_resolution_error(const constantPoolHandle& pool, int which, Symbol** message); protected: @@ -700,13 +700,13 @@ protected: TRAPS); // Variables holding commonly used klasses (preloaded) - static Klass* _well_known_klasses[]; + static InstanceKlass* _well_known_klasses[]; // Lazily loaded klasses - static Klass* volatile _abstract_ownable_synchronizer_klass; + static InstanceKlass* volatile _abstract_ownable_synchronizer_klass; // table of box klasses (int_klass, etc.) - static Klass* _box_klasses[T_VOID+1]; + static InstanceKlass* _box_klasses[T_VOID+1]; static oop _java_system_loader; diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 2b4e8452b02..1ec5d5bddeb 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -184,7 +184,7 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul if (HAS_PENDING_EXCEPTION) { tty->print("Verification for %s has", klassName); tty->print_cr(" exception pending %s ", - InstanceKlass::cast(PENDING_EXCEPTION->klass())->external_name()); + PENDING_EXCEPTION->klass()->external_name()); } else if (exception_name != NULL) { tty->print_cr("Verification for %s failed", klassName); } @@ -605,7 +605,7 @@ void ClassVerifier::verify_class(TRAPS) { } } -void ClassVerifier::verify_method(methodHandle m, TRAPS) { +void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { HandleMark hm(THREAD); _method = m; // initialize _method if (VerboseVerification) { @@ -1901,7 +1901,7 @@ void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, S } void ClassVerifier::verify_cp_index( - u2 bci, constantPoolHandle cp, int index, TRAPS) { + u2 bci, const constantPoolHandle& cp, int index, TRAPS) { int nconstants = cp->length(); if ((index <= 0) || (index >= nconstants)) { verify_error(ErrorContext::bad_cp_index(bci, index), @@ -1912,7 +1912,7 @@ void ClassVerifier::verify_cp_index( } void ClassVerifier::verify_cp_type( - u2 bci, int index, constantPoolHandle cp, unsigned int types, TRAPS) { + u2 bci, int index, const constantPoolHandle& cp, unsigned int types, TRAPS) { // In some situations, bytecode rewriting may occur while we're verifying. // In this case, a constant pool cache exists and some indices refer to that @@ -1931,7 +1931,7 @@ void ClassVerifier::verify_cp_type( } void ClassVerifier::verify_cp_class_type( - u2 bci, int index, constantPoolHandle cp, TRAPS) { + u2 bci, int index, const constantPoolHandle& cp, TRAPS) { verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); constantTag tag = cp->tag_at(index); if (!tag.is_klass() && !tag.is_unresolved_klass()) { @@ -2023,7 +2023,7 @@ bool ClassVerifier::is_protected_access(instanceKlassHandle this_class, void ClassVerifier::verify_ldc( int opcode, u2 index, StackMapFrame* current_frame, - constantPoolHandle cp, u2 bci, TRAPS) { + const constantPoolHandle& cp, u2 bci, TRAPS) { verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); constantTag tag = cp->tag_at(index); unsigned int types; @@ -2165,7 +2165,7 @@ bool ClassVerifier::name_in_supers( void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs, StackMapFrame* current_frame, - constantPoolHandle cp, + const constantPoolHandle& cp, bool allow_arrays, TRAPS) { u2 index = bcs->get_index_u2(); @@ -2477,7 +2477,7 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { void ClassVerifier::verify_invoke_init( RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool in_try_block, - bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table, + bool *this_uninit, const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS) { u2 bci = bcs->bci(); VerificationType type = current_frame->pop_stack( @@ -2613,7 +2613,7 @@ bool ClassVerifier::is_same_or_direct_interface( void ClassVerifier::verify_invoke_instructions( RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, bool in_try_block, bool *this_uninit, VerificationType return_type, - constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) { + const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS) { // Make sure the constant pool item is the right type u2 index = bcs->get_index_u2(); Bytecodes::Code opcode = bcs->raw_code(); @@ -2846,7 +2846,7 @@ void ClassVerifier::verify_invoke_instructions( if (sig_stream.type() != T_VOID) { if (method_name == vmSymbols::object_initializer_name()) { // method must have a void return type - /* Unreachable? Class file parser verifies that methods have + /* Unreachable? Class file parser verifies that methods with '<' have * void return */ verify_error(ErrorContext::bad_code(bci), "Return type must be void in method"); @@ -2878,7 +2878,7 @@ VerificationType ClassVerifier::get_newarray_type( } void ClassVerifier::verify_anewarray( - u2 bci, u2 index, constantPoolHandle cp, + u2 bci, u2 index, const constantPoolHandle& cp, StackMapFrame* current_frame, TRAPS) { verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); current_frame->pop_stack( diff --git a/hotspot/src/share/vm/classfile/verifier.hpp b/hotspot/src/share/vm/classfile/verifier.hpp index c9aa6d50789..e265355e733 100644 --- a/hotspot/src/share/vm/classfile/verifier.hpp +++ b/hotspot/src/share/vm/classfile/verifier.hpp @@ -262,14 +262,14 @@ class ClassVerifier : public StackObj { ErrorContext _error_context; // contains information about an error - void verify_method(methodHandle method, TRAPS); + void verify_method(const methodHandle& method, TRAPS); char* generate_code_data(methodHandle m, u4 code_length, TRAPS); void verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS); void verify_local_variable_table(u4 code_length, char* code_data, TRAPS); VerificationType cp_ref_index_to_type( - int index, constantPoolHandle cp, TRAPS) { + int index, const constantPoolHandle& cp, TRAPS) { return cp_index_to_type(cp->klass_ref_index_at(index), cp, THREAD); } @@ -277,10 +277,10 @@ class ClassVerifier : public StackObj { instanceKlassHandle this_class, Klass* target_class, Symbol* field_name, Symbol* field_sig, bool is_method); - void verify_cp_index(u2 bci, constantPoolHandle cp, int index, TRAPS); - void verify_cp_type(u2 bci, int index, constantPoolHandle cp, + void verify_cp_index(u2 bci, const constantPoolHandle& cp, int index, TRAPS); + void verify_cp_type(u2 bci, int index, const constantPoolHandle& cp, unsigned int types, TRAPS); - void verify_cp_class_type(u2 bci, int index, constantPoolHandle cp, TRAPS); + void verify_cp_class_type(u2 bci, int index, const constantPoolHandle& cp, TRAPS); u2 verify_stackmap_table( u2 stackmap_index, u2 bci, StackMapFrame* current_frame, @@ -292,7 +292,7 @@ class ClassVerifier : public StackObj { void verify_ldc( int opcode, u2 index, StackMapFrame *current_frame, - constantPoolHandle cp, u2 bci, TRAPS); + const constantPoolHandle& cp, u2 bci, TRAPS); void verify_switch( RawBytecodeStream* bcs, u4 code_length, char* code_data, @@ -300,12 +300,12 @@ class ClassVerifier : public StackObj { void verify_field_instructions( RawBytecodeStream* bcs, StackMapFrame* current_frame, - constantPoolHandle cp, bool allow_arrays, TRAPS); + const constantPoolHandle& cp, bool allow_arrays, TRAPS); void verify_invoke_init( RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool in_try_block, - bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table, + bool* this_uninit, const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS); // Used by ends_in_athrow() to push all handlers that contain bci onto the @@ -322,10 +322,10 @@ class ClassVerifier : public StackObj { void verify_invoke_instructions( RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, bool in_try_block, bool* this_uninit, VerificationType return_type, - constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS); + const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS); VerificationType get_newarray_type(u2 index, u2 bci, TRAPS); - void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp, + void verify_anewarray(u2 bci, u2 index, const constantPoolHandle& cp, StackMapFrame* current_frame, TRAPS); void verify_return_value( VerificationType return_type, VerificationType type, u2 offset, @@ -406,7 +406,7 @@ class ClassVerifier : public StackObj { int change_sig_to_verificationType( SignatureStream* sig_type, VerificationType* inference_type, TRAPS); - VerificationType cp_index_to_type(int index, constantPoolHandle cp, TRAPS) { + VerificationType cp_index_to_type(int index, const constantPoolHandle& cp, TRAPS) { return VerificationType::reference_type(cp->klass_name_at(index)); } diff --git a/hotspot/src/share/vm/classfile/vmSymbols.cpp b/hotspot/src/share/vm/classfile/vmSymbols.cpp index 9dbdb53a4d3..bfb99c67630 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -417,7 +417,7 @@ int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) { } } -bool vmIntrinsics::is_disabled_by_flags(methodHandle method) { +bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) { vmIntrinsics::ID id = method->intrinsic_id(); assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); @@ -425,10 +425,26 @@ bool vmIntrinsics::is_disabled_by_flags(methodHandle method) { // the following switch statement. if (!InlineNatives) { switch (id) { - case vmIntrinsics::_indexOf: - case vmIntrinsics::_compareTo: - case vmIntrinsics::_equals: + case vmIntrinsics::_indexOfL: + case vmIntrinsics::_indexOfU: + case vmIntrinsics::_indexOfUL: + case vmIntrinsics::_indexOfIL: + case vmIntrinsics::_indexOfIU: + case vmIntrinsics::_indexOfIUL: + case vmIntrinsics::_indexOfU_char: + case vmIntrinsics::_compareToL: + case vmIntrinsics::_compareToU: + case vmIntrinsics::_compareToLU: + case vmIntrinsics::_compareToUL: + case vmIntrinsics::_equalsL: + case vmIntrinsics::_equalsU: case vmIntrinsics::_equalsC: + case vmIntrinsics::_getCharStringU: + case vmIntrinsics::_putCharStringU: + case vmIntrinsics::_compressStringC: + case vmIntrinsics::_compressStringB: + case vmIntrinsics::_inflateStringC: + case vmIntrinsics::_inflateStringB: case vmIntrinsics::_getAndAddInt: case vmIntrinsics::_getAndAddLong: case vmIntrinsics::_getAndSetInt: @@ -437,6 +453,7 @@ bool vmIntrinsics::is_disabled_by_flags(methodHandle method) { case vmIntrinsics::_loadFence: case vmIntrinsics::_storeFence: case vmIntrinsics::_fullFence: + case vmIntrinsics::_hasNegatives: case vmIntrinsics::_Reference_get: break; default: @@ -619,19 +636,31 @@ bool vmIntrinsics::is_disabled_by_flags(methodHandle method) { // intrinsic mechanism. if (!InlineObjectCopy || !InlineArrayCopy) return true; break; - case vmIntrinsics::_compareTo: + case vmIntrinsics::_compareToL: + case vmIntrinsics::_compareToU: + case vmIntrinsics::_compareToLU: + case vmIntrinsics::_compareToUL: if (!SpecialStringCompareTo) return true; break; - case vmIntrinsics::_indexOf: + case vmIntrinsics::_indexOfL: + case vmIntrinsics::_indexOfU: + case vmIntrinsics::_indexOfUL: + case vmIntrinsics::_indexOfIL: + case vmIntrinsics::_indexOfIU: + case vmIntrinsics::_indexOfIUL: + case vmIntrinsics::_indexOfU_char: if (!SpecialStringIndexOf) return true; break; - case vmIntrinsics::_equals: + case vmIntrinsics::_equalsL: + case vmIntrinsics::_equalsU: if (!SpecialStringEquals) return true; break; + case vmIntrinsics::_equalsB: case vmIntrinsics::_equalsC: if (!SpecialArraysEquals) return true; break; case vmIntrinsics::_encodeISOArray: + case vmIntrinsics::_encodeByteISOArray: if (!SpecialEncodeISOArray) return true; break; case vmIntrinsics::_getCallerClass: diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index a08a397506b..f98f400064d 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -53,6 +53,8 @@ template(java_lang_Object, "java/lang/Object") \ template(java_lang_Class, "java/lang/Class") \ template(java_lang_String, "java/lang/String") \ + template(java_lang_StringLatin1, "java/lang/StringLatin1") \ + template(java_lang_StringUTF16, "java/lang/StringUTF16") \ template(java_lang_Thread, "java/lang/Thread") \ template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \ template(java_lang_Cloneable, "java/lang/Cloneable") \ @@ -381,9 +383,9 @@ template(park_event_name, "nativeParkEventPointer") \ template(cache_field_name, "cache") \ template(value_name, "value") \ - template(offset_name, "offset") \ - template(count_name, "count") \ template(hash_name, "hash") \ + template(coder_name, "coder") \ + template(compact_strings_name, "COMPACT_STRINGS") \ template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \ template(numberOfTrailingZeros_name, "numberOfTrailingZeros") \ template(bitCount_name, "bitCount") \ @@ -837,22 +839,66 @@ \ do_intrinsic(_equalsC, java_util_Arrays, equals_name, equalsC_signature, F_S) \ do_signature(equalsC_signature, "([C[C)Z") \ + do_intrinsic(_equalsB, java_util_Arrays, equals_name, equalsB_signature, F_S) \ + do_signature(equalsB_signature, "([B[B)Z") \ \ - do_intrinsic(_compareTo, java_lang_String, compareTo_name, string_int_signature, F_R) \ + do_intrinsic(_compressStringC, java_lang_StringUTF16, compress_name, encodeISOArray_signature, F_S) \ + do_name( compress_name, "compress") \ + do_intrinsic(_compressStringB, java_lang_StringUTF16, compress_name, indexOfI_signature, F_S) \ + do_intrinsic(_inflateStringC, java_lang_StringLatin1, inflate_name, inflateC_signature, F_S) \ + do_name( inflate_name, "inflate") \ + do_signature(inflateC_signature, "([BI[CII)V") \ + do_intrinsic(_inflateStringB, java_lang_StringLatin1, inflate_name, inflateB_signature, F_S) \ + do_signature(inflateB_signature, "([BI[BII)V") \ + do_intrinsic(_toBytesStringU, java_lang_StringUTF16, toBytes_name, toBytesU_signature, F_S) \ + do_name( toBytes_name, "toBytes") \ + do_signature(toBytesU_signature, "([CII)[B") \ + do_intrinsic(_getCharsStringU, java_lang_StringUTF16, getCharsU_name, getCharsU_signature, F_S) \ + do_name( getCharsU_name, "getChars") \ + do_signature(getCharsU_signature, "([BII[CI)V") \ + do_intrinsic(_getCharStringU, java_lang_StringUTF16, getChar_name, getCharStringU_signature, F_S) \ + do_signature(getCharStringU_signature, "([BI)C") \ + do_intrinsic(_putCharStringU, java_lang_StringUTF16, putChar_name, putCharStringU_signature, F_S) \ + do_signature(putCharStringU_signature, "([BII)V") \ + do_intrinsic(_compareToL, java_lang_StringLatin1,compareTo_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_compareToU, java_lang_StringUTF16, compareTo_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_compareToLU, java_lang_StringLatin1,compareToLU_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_compareToUL, java_lang_StringUTF16, compareToUL_name, compareTo_indexOf_signature, F_S) \ + do_signature(compareTo_indexOf_signature, "([B[B)I") \ do_name( compareTo_name, "compareTo") \ - do_intrinsic(_indexOf, java_lang_String, indexOf_name, string_int_signature, F_R) \ + do_name( compareToLU_name, "compareToUTF16") \ + do_name( compareToUL_name, "compareToLatin1") \ + do_intrinsic(_indexOfL, java_lang_StringLatin1,indexOf_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_indexOfU, java_lang_StringUTF16, indexOf_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_indexOfUL, java_lang_StringUTF16, indexOfUL_name, compareTo_indexOf_signature, F_S) \ + do_intrinsic(_indexOfIL, java_lang_StringLatin1,indexOf_name, indexOfI_signature, F_S) \ + do_intrinsic(_indexOfIU, java_lang_StringUTF16, indexOf_name, indexOfI_signature, F_S) \ + do_intrinsic(_indexOfIUL, java_lang_StringUTF16, indexOfUL_name, indexOfI_signature, F_S) \ + do_intrinsic(_indexOfU_char, java_lang_StringUTF16, indexOfChar_name, indexOfChar_signature, F_S) \ do_name( indexOf_name, "indexOf") \ - do_intrinsic(_equals, java_lang_String, equals_name, object_boolean_signature, F_R) \ + do_name( indexOfChar_name, "indexOfChar") \ + do_name( indexOfUL_name, "indexOfLatin1") \ + do_signature(indexOfI_signature, "([BI[BII)I") \ + do_signature(indexOfChar_signature, "([BIII)I") \ + do_intrinsic(_equalsL, java_lang_StringLatin1,equals_name, equalsB_signature, F_S) \ + do_intrinsic(_equalsU, java_lang_StringUTF16, equals_name, equalsB_signature, F_S) \ \ do_class(java_nio_Buffer, "java/nio/Buffer") \ do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \ do_name( checkIndex_name, "checkIndex") \ \ + do_class(java_lang_StringCoding, "java/lang/StringCoding") \ + do_intrinsic(_hasNegatives, java_lang_StringCoding, hasNegatives_name, hasNegatives_signature, F_S) \ + do_name( hasNegatives_name, "hasNegatives") \ + do_signature(hasNegatives_signature, "([BII)Z") \ + \ do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \ do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \ do_name( encodeISOArray_name, "implEncodeISOArray") \ do_signature(encodeISOArray_signature, "([CI[BII)I") \ \ + do_intrinsic(_encodeByteISOArray, java_lang_StringCoding, encodeISOArray_name, indexOfI_signature, F_S) \ + \ do_class(java_math_BigInteger, "java/math/BigInteger") \ do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S) \ do_name( multiplyToLen_name, "implMultiplyToLen") \ @@ -942,24 +988,25 @@ do_intrinsic(_updateByteBufferAdler32, java_util_zip_Adler32, updateByteBuffer_A_name, updateByteBuffer_signature, F_SN) \ do_name( updateByteBuffer_A_name, "updateByteBuffer") \ \ - /* support for sun.misc.Unsafe */ \ - do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ + /* support for Unsafe */ \ + do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ + do_class(jdk_internal_misc_Unsafe, "jdk/internal/misc/Unsafe") \ \ - do_intrinsic(_allocateInstance, sun_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \ - do_name( allocateInstance_name, "allocateInstance") \ - do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \ - do_intrinsic(_copyMemory, sun_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \ - do_name( copyMemory_name, "copyMemory") \ - do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \ - do_intrinsic(_loadFence, sun_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \ - do_name( loadFence_name, "loadFence") \ - do_alias( loadFence_signature, void_method_signature) \ - do_intrinsic(_storeFence, sun_misc_Unsafe, storeFence_name, storeFence_signature, F_RN) \ - do_name( storeFence_name, "storeFence") \ - do_alias( storeFence_signature, void_method_signature) \ - do_intrinsic(_fullFence, sun_misc_Unsafe, fullFence_name, fullFence_signature, F_RN) \ - do_name( fullFence_name, "fullFence") \ - do_alias( fullFence_signature, void_method_signature) \ + do_intrinsic(_allocateInstance, jdk_internal_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \ + do_name( allocateInstance_name, "allocateInstance") \ + do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \ + do_intrinsic(_copyMemory, jdk_internal_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \ + do_name( copyMemory_name, "copyMemory") \ + do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \ + do_intrinsic(_loadFence, jdk_internal_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \ + do_name( loadFence_name, "loadFence") \ + do_alias( loadFence_signature, void_method_signature) \ + do_intrinsic(_storeFence, jdk_internal_misc_Unsafe, storeFence_name, storeFence_signature, F_RN) \ + do_name( storeFence_name, "storeFence") \ + do_alias( storeFence_signature, void_method_signature) \ + do_intrinsic(_fullFence, jdk_internal_misc_Unsafe, fullFence_name, fullFence_signature, F_RN) \ + do_name( fullFence_name, "fullFence") \ + do_alias( fullFence_signature, void_method_signature) \ \ /* Custom branch frequencies profiling support for JSR292 */ \ do_class(java_lang_invoke_MethodHandleImpl, "java/lang/invoke/MethodHandleImpl") \ @@ -1000,24 +1047,24 @@ do_name(getFloat_name,"getFloat") do_name(putFloat_name,"putFloat") \ do_name(getDouble_name,"getDouble") do_name(putDouble_name,"putDouble") \ \ - do_intrinsic(_getObject, sun_misc_Unsafe, getObject_name, getObject_signature, F_RN) \ - do_intrinsic(_getBoolean, sun_misc_Unsafe, getBoolean_name, getBoolean_signature, F_RN) \ - do_intrinsic(_getByte, sun_misc_Unsafe, getByte_name, getByte_signature, F_RN) \ - do_intrinsic(_getShort, sun_misc_Unsafe, getShort_name, getShort_signature, F_RN) \ - do_intrinsic(_getChar, sun_misc_Unsafe, getChar_name, getChar_signature, F_RN) \ - do_intrinsic(_getInt, sun_misc_Unsafe, getInt_name, getInt_signature, F_RN) \ - do_intrinsic(_getLong, sun_misc_Unsafe, getLong_name, getLong_signature, F_RN) \ - do_intrinsic(_getFloat, sun_misc_Unsafe, getFloat_name, getFloat_signature, F_RN) \ - do_intrinsic(_getDouble, sun_misc_Unsafe, getDouble_name, getDouble_signature, F_RN) \ - do_intrinsic(_putObject, sun_misc_Unsafe, putObject_name, putObject_signature, F_RN) \ - do_intrinsic(_putBoolean, sun_misc_Unsafe, putBoolean_name, putBoolean_signature, F_RN) \ - do_intrinsic(_putByte, sun_misc_Unsafe, putByte_name, putByte_signature, F_RN) \ - do_intrinsic(_putShort, sun_misc_Unsafe, putShort_name, putShort_signature, F_RN) \ - do_intrinsic(_putChar, sun_misc_Unsafe, putChar_name, putChar_signature, F_RN) \ - do_intrinsic(_putInt, sun_misc_Unsafe, putInt_name, putInt_signature, F_RN) \ - do_intrinsic(_putLong, sun_misc_Unsafe, putLong_name, putLong_signature, F_RN) \ - do_intrinsic(_putFloat, sun_misc_Unsafe, putFloat_name, putFloat_signature, F_RN) \ - do_intrinsic(_putDouble, sun_misc_Unsafe, putDouble_name, putDouble_signature, F_RN) \ + do_intrinsic(_getObject, jdk_internal_misc_Unsafe, getObject_name, getObject_signature, F_RN) \ + do_intrinsic(_getBoolean, jdk_internal_misc_Unsafe, getBoolean_name, getBoolean_signature, F_RN) \ + do_intrinsic(_getByte, jdk_internal_misc_Unsafe, getByte_name, getByte_signature, F_RN) \ + do_intrinsic(_getShort, jdk_internal_misc_Unsafe, getShort_name, getShort_signature, F_RN) \ + do_intrinsic(_getChar, jdk_internal_misc_Unsafe, getChar_name, getChar_signature, F_RN) \ + do_intrinsic(_getInt, jdk_internal_misc_Unsafe, getInt_name, getInt_signature, F_RN) \ + do_intrinsic(_getLong, jdk_internal_misc_Unsafe, getLong_name, getLong_signature, F_RN) \ + do_intrinsic(_getFloat, jdk_internal_misc_Unsafe, getFloat_name, getFloat_signature, F_RN) \ + do_intrinsic(_getDouble, jdk_internal_misc_Unsafe, getDouble_name, getDouble_signature, F_RN) \ + do_intrinsic(_putObject, jdk_internal_misc_Unsafe, putObject_name, putObject_signature, F_RN) \ + do_intrinsic(_putBoolean, jdk_internal_misc_Unsafe, putBoolean_name, putBoolean_signature, F_RN) \ + do_intrinsic(_putByte, jdk_internal_misc_Unsafe, putByte_name, putByte_signature, F_RN) \ + do_intrinsic(_putShort, jdk_internal_misc_Unsafe, putShort_name, putShort_signature, F_RN) \ + do_intrinsic(_putChar, jdk_internal_misc_Unsafe, putChar_name, putChar_signature, F_RN) \ + do_intrinsic(_putInt, jdk_internal_misc_Unsafe, putInt_name, putInt_signature, F_RN) \ + do_intrinsic(_putLong, jdk_internal_misc_Unsafe, putLong_name, putLong_signature, F_RN) \ + do_intrinsic(_putFloat, jdk_internal_misc_Unsafe, putFloat_name, putFloat_signature, F_RN) \ + do_intrinsic(_putDouble, jdk_internal_misc_Unsafe, putDouble_name, putDouble_signature, F_RN) \ \ do_name(getObjectVolatile_name,"getObjectVolatile") do_name(putObjectVolatile_name,"putObjectVolatile") \ do_name(getBooleanVolatile_name,"getBooleanVolatile") do_name(putBooleanVolatile_name,"putBooleanVolatile") \ @@ -1029,38 +1076,38 @@ do_name(getFloatVolatile_name,"getFloatVolatile") do_name(putFloatVolatile_name,"putFloatVolatile") \ do_name(getDoubleVolatile_name,"getDoubleVolatile") do_name(putDoubleVolatile_name,"putDoubleVolatile") \ \ - do_intrinsic(_getObjectVolatile, sun_misc_Unsafe, getObjectVolatile_name, getObject_signature, F_RN) \ - do_intrinsic(_getBooleanVolatile, sun_misc_Unsafe, getBooleanVolatile_name, getBoolean_signature, F_RN) \ - do_intrinsic(_getByteVolatile, sun_misc_Unsafe, getByteVolatile_name, getByte_signature, F_RN) \ - do_intrinsic(_getShortVolatile, sun_misc_Unsafe, getShortVolatile_name, getShort_signature, F_RN) \ - do_intrinsic(_getCharVolatile, sun_misc_Unsafe, getCharVolatile_name, getChar_signature, F_RN) \ - do_intrinsic(_getIntVolatile, sun_misc_Unsafe, getIntVolatile_name, getInt_signature, F_RN) \ - do_intrinsic(_getLongVolatile, sun_misc_Unsafe, getLongVolatile_name, getLong_signature, F_RN) \ - do_intrinsic(_getFloatVolatile, sun_misc_Unsafe, getFloatVolatile_name, getFloat_signature, F_RN) \ - do_intrinsic(_getDoubleVolatile, sun_misc_Unsafe, getDoubleVolatile_name, getDouble_signature, F_RN) \ - do_intrinsic(_putObjectVolatile, sun_misc_Unsafe, putObjectVolatile_name, putObject_signature, F_RN) \ - do_intrinsic(_putBooleanVolatile, sun_misc_Unsafe, putBooleanVolatile_name, putBoolean_signature, F_RN) \ - do_intrinsic(_putByteVolatile, sun_misc_Unsafe, putByteVolatile_name, putByte_signature, F_RN) \ - do_intrinsic(_putShortVolatile, sun_misc_Unsafe, putShortVolatile_name, putShort_signature, F_RN) \ - do_intrinsic(_putCharVolatile, sun_misc_Unsafe, putCharVolatile_name, putChar_signature, F_RN) \ - do_intrinsic(_putIntVolatile, sun_misc_Unsafe, putIntVolatile_name, putInt_signature, F_RN) \ - do_intrinsic(_putLongVolatile, sun_misc_Unsafe, putLongVolatile_name, putLong_signature, F_RN) \ - do_intrinsic(_putFloatVolatile, sun_misc_Unsafe, putFloatVolatile_name, putFloat_signature, F_RN) \ - do_intrinsic(_putDoubleVolatile, sun_misc_Unsafe, putDoubleVolatile_name, putDouble_signature, F_RN) \ + do_intrinsic(_getObjectVolatile, jdk_internal_misc_Unsafe, getObjectVolatile_name, getObject_signature, F_RN) \ + do_intrinsic(_getBooleanVolatile, jdk_internal_misc_Unsafe, getBooleanVolatile_name, getBoolean_signature, F_RN) \ + do_intrinsic(_getByteVolatile, jdk_internal_misc_Unsafe, getByteVolatile_name, getByte_signature, F_RN) \ + do_intrinsic(_getShortVolatile, jdk_internal_misc_Unsafe, getShortVolatile_name, getShort_signature, F_RN) \ + do_intrinsic(_getCharVolatile, jdk_internal_misc_Unsafe, getCharVolatile_name, getChar_signature, F_RN) \ + do_intrinsic(_getIntVolatile, jdk_internal_misc_Unsafe, getIntVolatile_name, getInt_signature, F_RN) \ + do_intrinsic(_getLongVolatile, jdk_internal_misc_Unsafe, getLongVolatile_name, getLong_signature, F_RN) \ + do_intrinsic(_getFloatVolatile, jdk_internal_misc_Unsafe, getFloatVolatile_name, getFloat_signature, F_RN) \ + do_intrinsic(_getDoubleVolatile, jdk_internal_misc_Unsafe, getDoubleVolatile_name, getDouble_signature, F_RN) \ + do_intrinsic(_putObjectVolatile, jdk_internal_misc_Unsafe, putObjectVolatile_name, putObject_signature, F_RN) \ + do_intrinsic(_putBooleanVolatile, jdk_internal_misc_Unsafe, putBooleanVolatile_name, putBoolean_signature, F_RN) \ + do_intrinsic(_putByteVolatile, jdk_internal_misc_Unsafe, putByteVolatile_name, putByte_signature, F_RN) \ + do_intrinsic(_putShortVolatile, jdk_internal_misc_Unsafe, putShortVolatile_name, putShort_signature, F_RN) \ + do_intrinsic(_putCharVolatile, jdk_internal_misc_Unsafe, putCharVolatile_name, putChar_signature, F_RN) \ + do_intrinsic(_putIntVolatile, jdk_internal_misc_Unsafe, putIntVolatile_name, putInt_signature, F_RN) \ + do_intrinsic(_putLongVolatile, jdk_internal_misc_Unsafe, putLongVolatile_name, putLong_signature, F_RN) \ + do_intrinsic(_putFloatVolatile, jdk_internal_misc_Unsafe, putFloatVolatile_name, putFloat_signature, F_RN) \ + do_intrinsic(_putDoubleVolatile, jdk_internal_misc_Unsafe, putDoubleVolatile_name, putDouble_signature, F_RN) \ \ do_name(getShortUnaligned_name,"getShortUnaligned") do_name(putShortUnaligned_name,"putShortUnaligned") \ do_name(getCharUnaligned_name,"getCharUnaligned") do_name(putCharUnaligned_name,"putCharUnaligned") \ do_name(getIntUnaligned_name,"getIntUnaligned") do_name(putIntUnaligned_name,"putIntUnaligned") \ do_name(getLongUnaligned_name,"getLongUnaligned") do_name(putLongUnaligned_name,"putLongUnaligned") \ \ - do_intrinsic(_getShortUnaligned, sun_misc_Unsafe, getShortUnaligned_name, getShort_signature, F_R) \ - do_intrinsic(_getCharUnaligned, sun_misc_Unsafe, getCharUnaligned_name, getChar_signature, F_R) \ - do_intrinsic(_getIntUnaligned, sun_misc_Unsafe, getIntUnaligned_name, getInt_signature, F_R) \ - do_intrinsic(_getLongUnaligned, sun_misc_Unsafe, getLongUnaligned_name, getLong_signature, F_R) \ - do_intrinsic(_putShortUnaligned, sun_misc_Unsafe, putShortUnaligned_name, putShort_signature, F_R) \ - do_intrinsic(_putCharUnaligned, sun_misc_Unsafe, putCharUnaligned_name, putChar_signature, F_R) \ - do_intrinsic(_putIntUnaligned, sun_misc_Unsafe, putIntUnaligned_name, putInt_signature, F_R) \ - do_intrinsic(_putLongUnaligned, sun_misc_Unsafe, putLongUnaligned_name, putLong_signature, F_R) \ + do_intrinsic(_getShortUnaligned, jdk_internal_misc_Unsafe, getShortUnaligned_name, getShort_signature, F_R) \ + do_intrinsic(_getCharUnaligned, jdk_internal_misc_Unsafe, getCharUnaligned_name, getChar_signature, F_R) \ + do_intrinsic(_getIntUnaligned, jdk_internal_misc_Unsafe, getIntUnaligned_name, getInt_signature, F_R) \ + do_intrinsic(_getLongUnaligned, jdk_internal_misc_Unsafe, getLongUnaligned_name, getLong_signature, F_R) \ + do_intrinsic(_putShortUnaligned, jdk_internal_misc_Unsafe, putShortUnaligned_name, putShort_signature, F_R) \ + do_intrinsic(_putCharUnaligned, jdk_internal_misc_Unsafe, putCharUnaligned_name, putChar_signature, F_R) \ + do_intrinsic(_putIntUnaligned, jdk_internal_misc_Unsafe, putIntUnaligned_name, putInt_signature, F_R) \ + do_intrinsic(_putLongUnaligned, jdk_internal_misc_Unsafe, putLongUnaligned_name, putLong_signature, F_R) \ \ /* %%% these are redundant except perhaps for getAddress, but Unsafe has native methods for them */ \ do_signature(getByte_raw_signature, "(J)B") \ @@ -1082,66 +1129,67 @@ do_name( getAddress_name, "getAddress") \ do_name( putAddress_name, "putAddress") \ \ - do_intrinsic(_getByte_raw, sun_misc_Unsafe, getByte_name, getByte_raw_signature, F_RN) \ - do_intrinsic(_getShort_raw, sun_misc_Unsafe, getShort_name, getShort_raw_signature, F_RN) \ - do_intrinsic(_getChar_raw, sun_misc_Unsafe, getChar_name, getChar_raw_signature, F_RN) \ - do_intrinsic(_getInt_raw, sun_misc_Unsafe, getInt_name, long_int_signature, F_RN) \ - do_intrinsic(_getLong_raw, sun_misc_Unsafe, getLong_name, getLong_raw_signature, F_RN) \ - do_intrinsic(_getFloat_raw, sun_misc_Unsafe, getFloat_name, getFloat_raw_signature, F_RN) \ - do_intrinsic(_getDouble_raw, sun_misc_Unsafe, getDouble_name, getDouble_raw_signature, F_RN) \ - do_intrinsic(_getAddress_raw, sun_misc_Unsafe, getAddress_name, getAddress_raw_signature, F_RN) \ - do_intrinsic(_putByte_raw, sun_misc_Unsafe, putByte_name, putByte_raw_signature, F_RN) \ - do_intrinsic(_putShort_raw, sun_misc_Unsafe, putShort_name, putShort_raw_signature, F_RN) \ - do_intrinsic(_putChar_raw, sun_misc_Unsafe, putChar_name, putChar_raw_signature, F_RN) \ - do_intrinsic(_putInt_raw, sun_misc_Unsafe, putInt_name, putInt_raw_signature, F_RN) \ - do_intrinsic(_putLong_raw, sun_misc_Unsafe, putLong_name, putLong_raw_signature, F_RN) \ - do_intrinsic(_putFloat_raw, sun_misc_Unsafe, putFloat_name, putFloat_raw_signature, F_RN) \ - do_intrinsic(_putDouble_raw, sun_misc_Unsafe, putDouble_name, putDouble_raw_signature, F_RN) \ - do_intrinsic(_putAddress_raw, sun_misc_Unsafe, putAddress_name, putAddress_raw_signature, F_RN) \ + do_intrinsic(_getByte_raw, jdk_internal_misc_Unsafe, getByte_name, getByte_raw_signature, F_R) \ + do_intrinsic(_getShort_raw, jdk_internal_misc_Unsafe, getShort_name, getShort_raw_signature, F_R) \ + do_intrinsic(_getChar_raw, jdk_internal_misc_Unsafe, getChar_name, getChar_raw_signature, F_R) \ + do_intrinsic(_getInt_raw, jdk_internal_misc_Unsafe, getInt_name, long_int_signature, F_R) \ + do_intrinsic(_getLong_raw, jdk_internal_misc_Unsafe, getLong_name, getLong_raw_signature, F_R) \ + do_intrinsic(_getFloat_raw, jdk_internal_misc_Unsafe, getFloat_name, getFloat_raw_signature, F_R) \ + do_intrinsic(_getDouble_raw, jdk_internal_misc_Unsafe, getDouble_name, getDouble_raw_signature, F_R) \ + do_intrinsic(_getAddress_raw, jdk_internal_misc_Unsafe, getAddress_name, getAddress_raw_signature, F_R) \ + do_intrinsic(_putByte_raw, jdk_internal_misc_Unsafe, putByte_name, putByte_raw_signature, F_R) \ + do_intrinsic(_putShort_raw, jdk_internal_misc_Unsafe, putShort_name, putShort_raw_signature, F_R) \ + do_intrinsic(_putChar_raw, jdk_internal_misc_Unsafe, putChar_name, putChar_raw_signature, F_R) \ + do_intrinsic(_putInt_raw, jdk_internal_misc_Unsafe, putInt_name, putInt_raw_signature, F_R) \ + do_intrinsic(_putLong_raw, jdk_internal_misc_Unsafe, putLong_name, putLong_raw_signature, F_R) \ + do_intrinsic(_putFloat_raw, jdk_internal_misc_Unsafe, putFloat_name, putFloat_raw_signature, F_R) \ + do_intrinsic(_putDouble_raw, jdk_internal_misc_Unsafe, putDouble_name, putDouble_raw_signature, F_R) \ + do_intrinsic(_putAddress_raw, jdk_internal_misc_Unsafe, putAddress_name, putAddress_raw_signature, F_R) \ \ - do_intrinsic(_compareAndSwapObject, sun_misc_Unsafe, compareAndSwapObject_name, compareAndSwapObject_signature, F_RN) \ - do_name( compareAndSwapObject_name, "compareAndSwapObject") \ - do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \ - do_intrinsic(_compareAndSwapLong, sun_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_RN) \ - do_name( compareAndSwapLong_name, "compareAndSwapLong") \ - do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \ - do_intrinsic(_compareAndSwapInt, sun_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_RN) \ - do_name( compareAndSwapInt_name, "compareAndSwapInt") \ - do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \ - do_intrinsic(_putOrderedObject, sun_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_RN) \ - do_name( putOrderedObject_name, "putOrderedObject") \ - do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \ - do_intrinsic(_putOrderedLong, sun_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_RN) \ - do_name( putOrderedLong_name, "putOrderedLong") \ - do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \ - do_intrinsic(_putOrderedInt, sun_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_RN) \ - do_name( putOrderedInt_name, "putOrderedInt") \ - do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \ + do_intrinsic(_compareAndSwapObject, jdk_internal_misc_Unsafe, compareAndSwapObject_name, compareAndSwapObject_signature, F_R) \ + do_name( compareAndSwapObject_name, "compareAndSwapObject") \ + do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \ + do_intrinsic(_compareAndSwapLong, jdk_internal_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_R) \ + do_name( compareAndSwapLong_name, "compareAndSwapLong") \ + do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \ + do_intrinsic(_compareAndSwapInt, jdk_internal_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_R) \ + do_name( compareAndSwapInt_name, "compareAndSwapInt") \ + do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \ + do_intrinsic(_putOrderedObject, jdk_internal_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_R) \ + do_name( putOrderedObject_name, "putOrderedObject") \ + do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \ + do_intrinsic(_putOrderedLong, jdk_internal_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_R) \ + do_name( putOrderedLong_name, "putOrderedLong") \ + do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \ + do_intrinsic(_putOrderedInt, jdk_internal_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_R) \ + do_name( putOrderedInt_name, "putOrderedInt") \ + do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \ \ - do_intrinsic(_getAndAddInt, sun_misc_Unsafe, getAndAddInt_name, getAndAddInt_signature, F_R) \ - do_name( getAndAddInt_name, "getAndAddInt") \ - do_signature(getAndAddInt_signature, "(Ljava/lang/Object;JI)I" ) \ - do_intrinsic(_getAndAddLong, sun_misc_Unsafe, getAndAddLong_name, getAndAddLong_signature, F_R) \ - do_name( getAndAddLong_name, "getAndAddLong") \ - do_signature(getAndAddLong_signature, "(Ljava/lang/Object;JJ)J" ) \ - do_intrinsic(_getAndSetInt, sun_misc_Unsafe, getAndSetInt_name, getAndSetInt_signature, F_R) \ - do_name( getAndSetInt_name, "getAndSetInt") \ - do_alias( getAndSetInt_signature, /*"(Ljava/lang/Object;JI)I"*/ getAndAddInt_signature) \ - do_intrinsic(_getAndSetLong, sun_misc_Unsafe, getAndSetLong_name, getAndSetLong_signature, F_R) \ - do_name( getAndSetLong_name, "getAndSetLong") \ - do_alias( getAndSetLong_signature, /*"(Ljava/lang/Object;JJ)J"*/ getAndAddLong_signature) \ - do_intrinsic(_getAndSetObject, sun_misc_Unsafe, getAndSetObject_name, getAndSetObject_signature, F_R)\ - do_name( getAndSetObject_name, "getAndSetObject") \ - do_signature(getAndSetObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \ - \ - /* (2) Bytecode intrinsics */ \ - \ - do_intrinsic(_park, sun_misc_Unsafe, park_name, park_signature, F_RN) \ - do_name( park_name, "park") \ - do_signature(park_signature, "(ZJ)V") \ - do_intrinsic(_unpark, sun_misc_Unsafe, unpark_name, unpark_signature, F_RN) \ - do_name( unpark_name, "unpark") \ - do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \ + do_intrinsic(_getAndAddInt, jdk_internal_misc_Unsafe, getAndAddInt_name, getAndAddInt_signature, F_R) \ + do_name( getAndAddInt_name, "getAndAddInt") \ + do_signature(getAndAddInt_signature, "(Ljava/lang/Object;JI)I" ) \ + do_intrinsic(_getAndAddLong, jdk_internal_misc_Unsafe, getAndAddLong_name, getAndAddLong_signature, F_R) \ + do_name( getAndAddLong_name, "getAndAddLong") \ + do_signature(getAndAddLong_signature, "(Ljava/lang/Object;JJ)J" ) \ + do_intrinsic(_getAndSetInt, jdk_internal_misc_Unsafe, getAndSetInt_name, getAndSetInt_signature, F_R) \ + do_name( getAndSetInt_name, "getAndSetInt") \ + do_alias( getAndSetInt_signature, /*"(Ljava/lang/Object;JI)I"*/ getAndAddInt_signature) \ + do_intrinsic(_getAndSetLong, jdk_internal_misc_Unsafe, getAndSetLong_name, getAndSetLong_signature, F_R) \ + do_name( getAndSetLong_name, "getAndSetLong") \ + do_alias( getAndSetLong_signature, /*"(Ljava/lang/Object;JJ)J"*/ getAndAddLong_signature) \ + do_intrinsic(_getAndSetObject, jdk_internal_misc_Unsafe, getAndSetObject_name, getAndSetObject_signature, F_R)\ + do_name( getAndSetObject_name, "getAndSetObject") \ + do_signature(getAndSetObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \ + \ + /* (2) Bytecode intrinsics */ \ + \ + do_intrinsic(_park, jdk_internal_misc_Unsafe, park_name, park_signature, F_R) \ + do_name( park_name, "park") \ + do_signature(park_signature, "(ZJ)V") \ + do_intrinsic(_unpark, jdk_internal_misc_Unsafe, unpark_name, unpark_signature, F_R) \ + do_name( unpark_name, "unpark") \ + do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \ + \ do_intrinsic(_StringBuilder_void, java_lang_StringBuilder, object_initializer_name, void_method_signature, F_R) \ do_intrinsic(_StringBuilder_int, java_lang_StringBuilder, object_initializer_name, int_void_signature, F_R) \ do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature, F_R) \ @@ -1406,7 +1454,7 @@ public: // Returns true if a compiler intrinsic is disabled by command-line flags // and false otherwise. - static bool is_disabled_by_flags(methodHandle method); + static bool is_disabled_by_flags(const methodHandle& method); }; #endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP diff --git a/hotspot/src/share/vm/code/compiledIC.cpp b/hotspot/src/share/vm/code/compiledIC.cpp index 3184e2ee86c..ec3e3a8e072 100644 --- a/hotspot/src/share/vm/code/compiledIC.cpp +++ b/hotspot/src/share/vm/code/compiledIC.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -462,7 +462,7 @@ void CompiledIC::set_to_monomorphic(CompiledICInfo& info) { // is_optimized: Compiler has generated an optimized call (i.e., no inline // cache) static_bound: The call can be static bound (i.e, no need to use // inline cache) -void CompiledIC::compute_monomorphic_entry(methodHandle method, +void CompiledIC::compute_monomorphic_entry(const methodHandle& method, KlassHandle receiver_klass, bool is_optimized, bool static_bound, @@ -594,7 +594,7 @@ void CompiledStaticCall::set(const StaticCallInfo& info) { // Compute settings for a CompiledStaticCall. Since we might have to set // the stub when calling to the interpreter, we need to return arguments. -void CompiledStaticCall::compute_entry(methodHandle m, StaticCallInfo& info) { +void CompiledStaticCall::compute_entry(const methodHandle& m, StaticCallInfo& info) { nmethod* m_code = m->code(); info._callee = m; if (m_code != NULL && m_code->is_in_use()) { diff --git a/hotspot/src/share/vm/code/compiledIC.hpp b/hotspot/src/share/vm/code/compiledIC.hpp index d4d946e8336..cd1edbbaa36 100644 --- a/hotspot/src/share/vm/code/compiledIC.hpp +++ b/hotspot/src/share/vm/code/compiledIC.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -222,7 +222,7 @@ class CompiledIC: public ResourceObj { // allocation in the code cache fails. bool set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS); - static void compute_monomorphic_entry(methodHandle method, KlassHandle receiver_klass, + static void compute_monomorphic_entry(const methodHandle& method, KlassHandle receiver_klass, bool is_optimized, bool static_bound, CompiledICInfo& info, TRAPS); // Location @@ -324,7 +324,7 @@ class CompiledStaticCall: public NativeCall { void set(const StaticCallInfo& info); // Compute entry point given a method - static void compute_entry(methodHandle m, StaticCallInfo& info); + static void compute_entry(const methodHandle& m, StaticCallInfo& info); // Stub support address find_stub(); diff --git a/hotspot/src/share/vm/code/debugInfoRec.cpp b/hotspot/src/share/vm/code/debugInfoRec.cpp index f1cbf02223f..e82d9801d12 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.cpp +++ b/hotspot/src/share/vm/code/debugInfoRec.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -324,7 +324,7 @@ int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) { // must call add_safepoint before: it sets PcDesc and this routine uses // the last PcDesc set void DebugInformationRecorder::describe_scope(int pc_offset, - methodHandle methodH, + const methodHandle& methodH, ciMethod* method, int bci, bool reexecute, diff --git a/hotspot/src/share/vm/code/debugInfoRec.hpp b/hotspot/src/share/vm/code/debugInfoRec.hpp index 62930adbc79..d8daac3a0f2 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.hpp +++ b/hotspot/src/share/vm/code/debugInfoRec.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -98,7 +98,7 @@ class DebugInformationRecorder: public ResourceObj { // by add_non_safepoint, and the locals, expressions, and monitors // must all be null. void describe_scope(int pc_offset, - methodHandle methodH, + const methodHandle& methodH, ciMethod* method, int bci, bool reexecute, diff --git a/hotspot/src/share/vm/code/dependencies.cpp b/hotspot/src/share/vm/code/dependencies.cpp index ed77e17b7f5..c941f404276 100644 --- a/hotspot/src/share/vm/code/dependencies.cpp +++ b/hotspot/src/share/vm/code/dependencies.cpp @@ -151,7 +151,7 @@ void Dependencies::assert_has_no_finalizable_subclasses(Klass* ctxk) { } void Dependencies::assert_leaf_type(Klass* ctxk) { - if (ctxk->oop_is_array()) { + if (ctxk->is_array_klass()) { // As a special case, support this assertion on an array type, // which reduces to an assertion on its element type. // Note that this cannot be done with assertions that @@ -1084,10 +1084,10 @@ class ClassHierarchyWalker { return true; // Must punt the assertion to true. Klass* k = ctxk; Method* lm = k->lookup_method(m->name(), m->signature()); - if (lm == NULL && k->oop_is_instance()) { + if (lm == NULL && k->is_instance_klass()) { // It might be an interface method - lm = ((InstanceKlass*)k)->lookup_method_in_ordered_interfaces(m->name(), - m->signature()); + lm = InstanceKlass::cast(k)->lookup_method_in_ordered_interfaces(m->name(), + m->signature()); } if (lm == m) // Method m is inherited into ctxk. @@ -1135,7 +1135,7 @@ class ClassHierarchyWalker { bool is_witness(Klass* k) { if (doing_subtype_search()) { return Dependencies::is_concrete_klass(k); - } else if (!k->oop_is_instance()) { + } else if (!k->is_instance_klass()) { return false; // no methods to find in an array type } else { // Search class hierarchy first. @@ -1840,20 +1840,20 @@ void DepChange::print() { Klass* k = str.klass(); switch (str.change_type()) { case Change_new_type: - tty->print_cr(" dependee = %s", InstanceKlass::cast(k)->external_name()); + tty->print_cr(" dependee = %s", k->external_name()); break; case Change_new_sub: if (!WizardMode) { ++nsup; } else { - tty->print_cr(" context super = %s", InstanceKlass::cast(k)->external_name()); + tty->print_cr(" context super = %s", k->external_name()); } break; case Change_new_impl: if (!WizardMode) { ++nint; } else { - tty->print_cr(" context interface = %s", InstanceKlass::cast(k)->external_name()); + tty->print_cr(" context interface = %s", k->external_name()); } break; } @@ -1885,7 +1885,7 @@ bool DepChange::ContextStream::next() { case Change_new_sub: // 6598190: brackets workaround Sun Studio C++ compiler bug 6629277 { - _klass = InstanceKlass::cast(_klass)->super(); + _klass = _klass->super(); if (_klass != NULL) { return true; } @@ -1931,7 +1931,7 @@ KlassDepChange::~KlassDepChange() { } bool KlassDepChange::involves_context(Klass* k) { - if (k == NULL || !k->oop_is_instance()) { + if (k == NULL || !k->is_instance_klass()) { return false; } InstanceKlass* ik = InstanceKlass::cast(k); diff --git a/hotspot/src/share/vm/code/dependencies.hpp b/hotspot/src/share/vm/code/dependencies.hpp index a2ffeeb08d1..e9c26011695 100644 --- a/hotspot/src/share/vm/code/dependencies.hpp +++ b/hotspot/src/share/vm/code/dependencies.hpp @@ -351,7 +351,7 @@ class Dependencies: public ResourceObj { #if INCLUDE_JVMCI private: static void check_ctxk(Klass* ctxk) { - assert(ctxk->oop_is_instance(), "java types only"); + assert(ctxk->is_instance_klass(), "java types only"); } static void check_ctxk_abstract(Klass* ctxk) { check_ctxk(ctxk); diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 04f3f314603..50e2b4c6930 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -558,7 +558,7 @@ void nmethod::init_defaults() { #endif } -nmethod* nmethod::new_native_nmethod(methodHandle method, +nmethod* nmethod::new_native_nmethod(const methodHandle& method, int compile_id, CodeBuffer *code_buffer, int vep_offset, @@ -593,7 +593,7 @@ nmethod* nmethod::new_native_nmethod(methodHandle method, return nm; } -nmethod* nmethod::new_nmethod(methodHandle method, +nmethod* nmethod::new_nmethod(const methodHandle& method, int compile_id, int entry_bci, CodeOffsets* offsets, @@ -674,10 +674,6 @@ nmethod* nmethod::new_nmethod(methodHandle method, return nm; } -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4355) // warning C4355: 'this' : used in base member initializer list -#endif // For native wrappers nmethod::nmethod( Method* method, @@ -767,10 +763,6 @@ nmethod::nmethod( } } -#ifdef _MSC_VER -#pragma warning(pop) -#endif - void* nmethod::operator new(size_t size, int nmethod_size, int comp_level) throw () { return CodeCache::allocate(nmethod_size, CodeCache::get_code_blob_type(comp_level)); } @@ -1350,20 +1342,17 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) { // Unregister must be done before the state change Universe::heap()->unregister_nmethod(this); + _state = unloaded; + #if INCLUDE_JVMCI // The method can only be unloaded after the pointer to the installed code // Java wrapper is no longer alive. Here we need to clear out this weak // reference to the dead object. Nulling out the reference has to happen // after the method is unregistered since the original value may be still // tracked by the rset. - if (_jvmci_installed_code != NULL) { - InstalledCode::set_address(_jvmci_installed_code, 0); - _jvmci_installed_code = NULL; - } + maybe_invalidate_installed_code(); #endif - _state = unloaded; - // Log the unloading. log_state_change(); @@ -1525,12 +1514,8 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) { } else { assert(state == not_entrant, "other cases may need to be handled differently"); } -#if INCLUDE_JVMCI - if (_jvmci_installed_code != NULL) { - // Break the link between nmethod and InstalledCode such that the nmethod can subsequently be flushed safely. - InstalledCode::set_address(_jvmci_installed_code, 0); - } -#endif + + JVMCI_ONLY(maybe_invalidate_installed_code()); if (TraceCreateZombies) { ResourceMark m; @@ -1615,7 +1600,11 @@ void nmethod::flush_dependencies(BoolObjectClosure* is_alive) { // During GC the is_alive closure is non-NULL, and is used to // determine liveness of dependees that need to be updated. if (is_alive == NULL || klass->is_loader_alive(is_alive)) { - InstanceKlass::cast(klass)->remove_dependent_nmethod(this); + // The GC defers deletion of this entry, since there might be multiple threads + // iterating over the _dependencies graph. Other call paths are single-threaded + // and may delete it immediately. + bool delete_immediately = is_alive == NULL; + InstanceKlass::cast(klass)->remove_dependent_nmethod(this, delete_immediately); } } } @@ -2306,7 +2295,7 @@ void nmethod::oops_do_marking_epilogue() { assert(cur != NULL, "not NULL-terminated"); nmethod* next = cur->_oops_do_mark_link; cur->_oops_do_mark_link = NULL; - cur->verify_oop_relocations(); + DEBUG_ONLY(cur->verify_oop_relocations()); NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark")); cur = next; } @@ -3004,7 +2993,7 @@ void nmethod::print_dependencies() { deps.print_dependency(); Klass* ctxk = deps.context_type(); if (ctxk != NULL) { - if (ctxk->oop_is_instance() && ((InstanceKlass*)ctxk)->is_dependent_nmethod(this)) { + if (ctxk->is_instance_klass() && InstanceKlass::cast(ctxk)->is_dependent_nmethod(this)) { tty->print_cr(" [nmethod<=klass]%s", ctxk->external_name()); } } @@ -3384,6 +3373,22 @@ void nmethod::print_statistics() { #endif // !PRODUCT #if INCLUDE_JVMCI +void nmethod::maybe_invalidate_installed_code() { + if (_jvmci_installed_code != NULL) { + if (!is_alive()) { + // Break the link between nmethod and InstalledCode such that the nmethod + // can subsequently be flushed safely. The link must be maintained while + // the method could have live activations since invalidateInstalledCode + // might want to invalidate all existing activations. + InstalledCode::set_address(_jvmci_installed_code, 0); + InstalledCode::set_entryPoint(_jvmci_installed_code, 0); + _jvmci_installed_code = NULL; + } else if (is_not_entrant()) { + InstalledCode::set_entryPoint(_jvmci_installed_code, 0); + } + } +} + char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) { if (!this->is_compiled_by_jvmci()) { return NULL; diff --git a/hotspot/src/share/vm/code/nmethod.hpp b/hotspot/src/share/vm/code/nmethod.hpp index 2125d9680bd..9510caed36e 100644 --- a/hotspot/src/share/vm/code/nmethod.hpp +++ b/hotspot/src/share/vm/code/nmethod.hpp @@ -307,7 +307,7 @@ class nmethod : public CodeBlob { public: // create nmethod with entry_bci - static nmethod* new_nmethod(methodHandle method, + static nmethod* new_nmethod(const methodHandle& method, int compile_id, int entry_bci, CodeOffsets* offsets, @@ -327,7 +327,7 @@ class nmethod : public CodeBlob { #endif ); - static nmethod* new_native_nmethod(methodHandle method, + static nmethod* new_native_nmethod(const methodHandle& method, int compile_id, CodeBuffer *code_buffer, int vep_offset, @@ -603,6 +603,7 @@ public: oop jvmci_installed_code() { return _jvmci_installed_code ; } char* jvmci_installed_code_name(char* buf, size_t buflen); void set_jvmci_installed_code(oop installed_code) { _jvmci_installed_code = installed_code; } + void maybe_invalidate_installed_code(); oop speculation_log() { return _speculation_log ; } void set_speculation_log(oop speculation_log) { _speculation_log = speculation_log; } #endif diff --git a/hotspot/src/share/vm/code/relocInfo.cpp b/hotspot/src/share/vm/code/relocInfo.cpp index 4ae8099a384..50b0517457d 100644 --- a/hotspot/src/share/vm/code/relocInfo.cpp +++ b/hotspot/src/share/vm/code/relocInfo.cpp @@ -438,10 +438,10 @@ void Relocation::const_set_data_value(address x) { void Relocation::const_verify_data_value(address x) { #ifdef _LP64 if (format() == relocInfo::narrow_oop_in_const) { - assert(*(narrowOop*)addr() == oopDesc::encode_heap_oop((oop) x), "must agree"); + guarantee(*(narrowOop*)addr() == oopDesc::encode_heap_oop((oop) x), "must agree"); } else { #endif - assert(*(address*)addr() == x, "must agree"); + guarantee(*(address*)addr() == x, "must agree"); #ifdef _LP64 } #endif diff --git a/hotspot/src/share/vm/compiler/abstractCompiler.hpp b/hotspot/src/share/vm/compiler/abstractCompiler.hpp index 1c5304f6475..b02d85eaf57 100644 --- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp +++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp @@ -111,7 +111,7 @@ class AbstractCompiler : public CHeapObj { // Missing feature tests virtual bool supports_native() { return true; } virtual bool supports_osr () { return true; } - virtual bool can_compile_method(methodHandle method) { return true; } + virtual bool can_compile_method(const methodHandle& method) { return true; } // Determine if the current compiler provides an intrinsic // for method 'method'. An intrinsic is available if: @@ -138,7 +138,7 @@ class AbstractCompiler : public CHeapObj { // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp // for more details. - virtual bool is_intrinsic_available(methodHandle method, DirectiveSet* directive) { + virtual bool is_intrinsic_available(const methodHandle& method, DirectiveSet* directive) { return is_intrinsic_supported(method) && !directive->is_intrinsic_disabled(method) && !vmIntrinsics::is_disabled_by_flags(method); @@ -152,7 +152,7 @@ class AbstractCompiler : public CHeapObj { // by default no intrinsics are supported by a compiler except // the ones listed in the method. Overriding methods should conform // to this behavior. - virtual bool is_intrinsic_supported(methodHandle method) { + virtual bool is_intrinsic_supported(const methodHandle& method) { return false; } @@ -162,6 +162,9 @@ class AbstractCompiler : public CHeapObj { bool is_jvmci() { return _type == jvmci; } bool is_shark() { return _type == shark; } + // Extra tests to identify trivial methods for the tiered compilation policy. + virtual bool is_trivial(Method* method) { return false; } + // Customization virtual void initialize () = 0; diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 7e28599fda1..b508b2e893c 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -790,10 +790,10 @@ void CompileBroker::mark_on_stack() { // CompileBroker::compile_method // // Request compilation of a method. -void CompileBroker::compile_method_base(methodHandle method, +void CompileBroker::compile_method_base(const methodHandle& method, int osr_bci, int comp_level, - methodHandle hot_method, + const methodHandle& hot_method, int hot_count, const char* comment, Thread* thread) { @@ -803,7 +803,7 @@ void CompileBroker::compile_method_base(methodHandle method, } guarantee(!method->is_abstract(), "cannot compile abstract methods"); - assert(method->method_holder()->oop_is_instance(), + assert(method->method_holder()->is_instance_klass(), "sanity check"); assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized"); @@ -993,12 +993,12 @@ void CompileBroker::compile_method_base(methodHandle method, } -nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, +nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, int comp_level, - methodHandle hot_method, int hot_count, + const methodHandle& hot_method, int hot_count, const char* comment, Thread* THREAD) { // make sure arguments make sense - assert(method->method_holder()->oop_is_instance(), "not an instance method"); + assert(method->method_holder()->is_instance_klass(), "not an instance method"); assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods"); assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized"); @@ -1134,9 +1134,9 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, // CompileBroker::compilation_is_complete // // See if compilation of this method is already complete. -bool CompileBroker::compilation_is_complete(methodHandle method, - int osr_bci, - int comp_level) { +bool CompileBroker::compilation_is_complete(const methodHandle& method, + int osr_bci, + int comp_level) { bool is_osr = (osr_bci != standard_entry_bci); if (is_osr) { if (method->is_not_osr_compilable(comp_level)) { @@ -1167,7 +1167,7 @@ bool CompileBroker::compilation_is_complete(methodHandle method, * versa). This can be remedied by a full queue search to disambiguate * cases. If it is deemed profitable, this may be done. */ -bool CompileBroker::compilation_is_in_queue(methodHandle method) { +bool CompileBroker::compilation_is_in_queue(const methodHandle& method) { return method->queued_for_compilation(); } @@ -1175,7 +1175,7 @@ bool CompileBroker::compilation_is_in_queue(methodHandle method) { // CompileBroker::compilation_is_prohibited // // See if this compilation is not allowed. -bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level) { +bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level) { bool is_native = method->is_native(); // Some compilers may not support the compilation of natives. AbstractCompiler *comp = compiler(comp_level); @@ -1222,7 +1222,7 @@ bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci, * and the ID is not within the specified range, the method is not compiled and 0 is returned. * The function also allows to generate separate compilation IDs for OSR compilations. */ -int CompileBroker::assign_compile_id(methodHandle method, int osr_bci) { +int CompileBroker::assign_compile_id(const methodHandle& method, int osr_bci) { #ifdef ASSERT bool is_osr = (osr_bci != standard_entry_bci); int id; @@ -1257,7 +1257,7 @@ int CompileBroker::assign_compile_id(methodHandle method, int osr_bci) { // CompileBroker::assign_compile_id_unlocked // // Public wrapper for assign_compile_id that acquires the needed locks -uint CompileBroker::assign_compile_id_unlocked(Thread* thread, methodHandle method, int osr_bci) { +uint CompileBroker::assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci) { MutexLocker locker(MethodCompileQueue_lock, thread); return assign_compile_id(method, osr_bci); } @@ -1274,7 +1274,7 @@ bool CompileBroker::is_compile_blocking() { // ------------------------------------------------------------------ // CompileBroker::preload_classes -void CompileBroker::preload_classes(methodHandle method, TRAPS) { +void CompileBroker::preload_classes(const methodHandle& method, TRAPS) { // Move this code over from c1_Compiler.cpp ShouldNotReachHere(); } @@ -1285,15 +1285,15 @@ void CompileBroker::preload_classes(methodHandle method, TRAPS) { // // Create a CompileTask object representing the current request for // compilation. Add this task to the queue. -CompileTask* CompileBroker::create_compile_task(CompileQueue* queue, - int compile_id, - methodHandle method, - int osr_bci, - int comp_level, - methodHandle hot_method, - int hot_count, - const char* comment, - bool blocking) { +CompileTask* CompileBroker::create_compile_task(CompileQueue* queue, + int compile_id, + const methodHandle& method, + int osr_bci, + int comp_level, + const methodHandle& hot_method, + int hot_count, + const char* comment, + bool blocking) { CompileTask* new_task = CompileTask::allocate(); new_task->initialize(compile_id, method, osr_bci, comp_level, hot_method, hot_count, comment, @@ -1891,7 +1891,7 @@ void CompileBroker::handle_full_code_cache(int code_blob_type) { // CompileBroker::set_last_compile // // Record this compilation for debugging purposes. -void CompileBroker::set_last_compile(CompilerThread* thread, methodHandle method, bool is_osr, int comp_level) { +void CompileBroker::set_last_compile(CompilerThread* thread, const methodHandle& method, bool is_osr, int comp_level) { ResourceMark rm; char* method_name = method->name()->as_C_string(); strncpy(_last_method_compiled, method_name, CompileBroker::name_buffer_length); @@ -2242,4 +2242,3 @@ void CompileBroker::print_compiler_threads_on(outputStream* st) { st->cr(); #endif } - diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index b469aebd769..9c0709aa28f 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -145,7 +145,7 @@ class CompileBroker: AllStatic { // Compile type Information for print_last_compile() and CompilerCounters enum { no_compile, normal_compile, osr_compile, native_compile }; - static int assign_compile_id (methodHandle method, int osr_bci); + static int assign_compile_id (const methodHandle& method, int osr_bci); private: @@ -218,33 +218,33 @@ class CompileBroker: AllStatic { static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS); static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count); - static bool compilation_is_complete (methodHandle method, int osr_bci, int comp_level); - static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level); + static bool compilation_is_complete (const methodHandle& method, int osr_bci, int comp_level); + static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level); static bool is_compile_blocking(); - static void preload_classes (methodHandle method, TRAPS); + static void preload_classes (const methodHandle& method, TRAPS); - static CompileTask* create_compile_task(CompileQueue* queue, - int compile_id, - methodHandle method, - int osr_bci, - int comp_level, - methodHandle hot_method, - int hot_count, - const char* comment, - bool blocking); + static CompileTask* create_compile_task(CompileQueue* queue, + int compile_id, + const methodHandle& method, + int osr_bci, + int comp_level, + const methodHandle& hot_method, + int hot_count, + const char* comment, + bool blocking); static void wait_for_completion(CompileTask* task); static void invoke_compiler_on_method(CompileTask* task); static void post_compile(CompilerThread* thread, CompileTask* task, EventCompilation& event, bool success, ciEnv* ci_env); - static void set_last_compile(CompilerThread *thread, methodHandle method, bool is_osr, int comp_level); + static void set_last_compile(CompilerThread *thread, const methodHandle& method, bool is_osr, int comp_level); static void push_jni_handle_block(); static void pop_jni_handle_block(); static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task); - static void compile_method_base(methodHandle method, + static void compile_method_base(const methodHandle& method, int osr_bci, int comp_level, - methodHandle hot_method, + const methodHandle& hot_method, int hot_count, const char* comment, Thread* thread); @@ -269,7 +269,7 @@ public: return NULL; } - static bool compilation_is_in_queue(methodHandle method); + static bool compilation_is_in_queue(const methodHandle& method); static void print_compile_queues(outputStream* st); static void print_directives(outputStream* st); static int queue_size(int comp_level) { @@ -278,15 +278,15 @@ public: } static void compilation_init(); static void init_compiler_thread_log(); - static nmethod* compile_method(methodHandle method, + static nmethod* compile_method(const methodHandle& method, int osr_bci, int comp_level, - methodHandle hot_method, + const methodHandle& hot_method, int hot_count, const char* comment, Thread* thread); // Acquire any needed locks and assign a compile id - static uint assign_compile_id_unlocked(Thread* thread, methodHandle method, int osr_bci); + static uint assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci); static void compiler_thread_loop(); static uint get_compilation_id() { return _compilation_id; } diff --git a/hotspot/src/share/vm/compiler/compileTask.cpp b/hotspot/src/share/vm/compiler/compileTask.cpp index a01b960899c..0cd15c9592e 100644 --- a/hotspot/src/share/vm/compiler/compileTask.cpp +++ b/hotspot/src/share/vm/compiler/compileTask.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -76,10 +76,10 @@ void CompileTask::free(CompileTask* task) { void CompileTask::initialize(int compile_id, - methodHandle method, + const methodHandle& method, int osr_bci, int comp_level, - methodHandle hot_method, + const methodHandle& hot_method, int hot_count, const char* comment, bool is_blocking) { diff --git a/hotspot/src/share/vm/compiler/compileTask.hpp b/hotspot/src/share/vm/compiler/compileTask.hpp index 68c93386187..b35d1345095 100644 --- a/hotspot/src/share/vm/compiler/compileTask.hpp +++ b/hotspot/src/share/vm/compiler/compileTask.hpp @@ -71,8 +71,8 @@ class CompileTask : public CHeapObj { _lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock"); } - void initialize(int compile_id, methodHandle method, int osr_bci, int comp_level, - methodHandle hot_method, int hot_count, const char* comment, + void initialize(int compile_id, const methodHandle& method, int osr_bci, int comp_level, + const methodHandle& hot_method, int hot_count, const char* comment, bool is_blocking); static CompileTask* allocate(); diff --git a/hotspot/src/share/vm/compiler/compilerOracle.cpp b/hotspot/src/share/vm/compiler/compilerOracle.cpp index 471249305af..15d5d3a091c 100644 --- a/hotspot/src/share/vm/compiler/compilerOracle.cpp +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp @@ -317,7 +317,7 @@ static void add_predicate(OracleCommand command, BasicMatcher* bm) { } template -bool CompilerOracle::has_option_value(methodHandle method, const char* option, T& value) { +bool CompilerOracle::has_option_value(const methodHandle& method, const char* option, T& value) { if (option_list != NULL) { TypedMethodOptionMatcher* m = option_list->match(method, option, get_type_for()); if (m != NULL) { @@ -333,19 +333,19 @@ bool CompilerOracle::has_any_option() { } // Explicit instantiation for all OptionTypes supported. -template bool CompilerOracle::has_option_value(methodHandle method, const char* option, intx& value); -template bool CompilerOracle::has_option_value(methodHandle method, const char* option, uintx& value); -template bool CompilerOracle::has_option_value(methodHandle method, const char* option, bool& value); -template bool CompilerOracle::has_option_value(methodHandle method, const char* option, ccstr& value); -template bool CompilerOracle::has_option_value(methodHandle method, const char* option, double& value); +template bool CompilerOracle::has_option_value(const methodHandle& method, const char* option, intx& value); +template bool CompilerOracle::has_option_value(const methodHandle& method, const char* option, uintx& value); +template bool CompilerOracle::has_option_value(const methodHandle& method, const char* option, bool& value); +template bool CompilerOracle::has_option_value(const methodHandle& method, const char* option, ccstr& value); +template bool CompilerOracle::has_option_value(const methodHandle& method, const char* option, double& value); -bool CompilerOracle::has_option_string(methodHandle method, const char* option) { +bool CompilerOracle::has_option_string(const methodHandle& method, const char* option) { bool value = false; has_option_value(method, option, value); return value; } -bool CompilerOracle::should_exclude(methodHandle method) { +bool CompilerOracle::should_exclude(const methodHandle& method) { if (check_predicate(ExcludeCommand, method)) { return true; } @@ -355,15 +355,15 @@ bool CompilerOracle::should_exclude(methodHandle method) { return false; } -bool CompilerOracle::should_inline(methodHandle method) { +bool CompilerOracle::should_inline(const methodHandle& method) { return (check_predicate(InlineCommand, method)); } -bool CompilerOracle::should_not_inline(methodHandle method) { +bool CompilerOracle::should_not_inline(const methodHandle& method) { return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method); } -bool CompilerOracle::should_print(methodHandle method) { +bool CompilerOracle::should_print(const methodHandle& method) { return check_predicate(PrintCommand, method); } @@ -371,13 +371,13 @@ bool CompilerOracle::should_print_methods() { return lists[PrintCommand] != NULL; } -bool CompilerOracle::should_log(methodHandle method) { +bool CompilerOracle::should_log(const methodHandle& method) { if (!LogCompilation) return false; if (lists[LogCommand] == NULL) return true; // by default, log all return (check_predicate(LogCommand, method)); } -bool CompilerOracle::should_break_at(methodHandle method) { +bool CompilerOracle::should_break_at(const methodHandle& method) { return check_predicate(BreakCommand, method); } @@ -757,7 +757,7 @@ void CompilerOracle::append_comment_to_file(const char* message) { stream.cr(); } -void CompilerOracle::append_exclude_to_file(methodHandle method) { +void CompilerOracle::append_exclude_to_file(const methodHandle& method) { assert(has_command_file(), "command file must be specified"); fileStream stream(fopen(cc_file(), "at")); stream.print("exclude "); diff --git a/hotspot/src/share/vm/compiler/compilerOracle.hpp b/hotspot/src/share/vm/compiler/compilerOracle.hpp index 454fc6317d4..9b731ebb2e0 100644 --- a/hotspot/src/share/vm/compiler/compilerOracle.hpp +++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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,31 +46,31 @@ class CompilerOracle : AllStatic { static void parse_from_file(); // Tells whether we to exclude compilation of method - static bool should_exclude(methodHandle method); + static bool should_exclude(const methodHandle& method); static bool should_exclude_quietly() { return _quiet; } // Tells whether we want to inline this method - static bool should_inline(methodHandle method); + static bool should_inline(const methodHandle& method); // Tells whether we want to disallow inlining of this method - static bool should_not_inline(methodHandle method); + static bool should_not_inline(const methodHandle& method); // Tells whether we should print the assembly for this method - static bool should_print(methodHandle method); + static bool should_print(const methodHandle& method); // Tells whether we should log the compilation data for this method - static bool should_log(methodHandle method); + static bool should_log(const methodHandle& method); // Tells whether to break when compiling method - static bool should_break_at(methodHandle method); + static bool should_break_at(const methodHandle& method); // Check to see if this method has option set for it - static bool has_option_string(methodHandle method, const char * option); + static bool has_option_string(const methodHandle& method, const char * option); // Check if method has option and value set. If yes, overwrite value and return true, // otherwise leave value unchanged and return false. template - static bool has_option_value(methodHandle method, const char* option, T& value); + static bool has_option_value(const methodHandle& method, const char* option, T& value); // Fast check if there is any option available that compile control needs to know about static bool has_any_option(); @@ -83,7 +83,7 @@ class CompilerOracle : AllStatic { // For updating the oracle file static void append_comment_to_file(const char* message); - static void append_exclude_to_file(methodHandle method); + static void append_exclude_to_file(const methodHandle& method); // Tells whether there are any methods to print for print_method_statistics() static bool should_print_methods(); diff --git a/hotspot/src/share/vm/compiler/disassembler.cpp b/hotspot/src/share/vm/compiler/disassembler.cpp index 82b0291f2d6..1ac15590cd0 100644 --- a/hotspot/src/share/vm/compiler/disassembler.cpp +++ b/hotspot/src/share/vm/compiler/disassembler.cpp @@ -86,6 +86,12 @@ bool Disassembler::load_library() { os::jvm_path(buf, sizeof(buf)); int jvm_offset = -1; int lib_offset = -1; +#ifdef STATIC_BUILD + char* p = strrchr(buf, '/'); + *p = '\0'; + strcat(p, "/lib/"); + lib_offset = jvm_offset = strlen(buf); +#else { // Match "jvm[^/]*" in jvm_path. const char* base = buf; @@ -94,6 +100,7 @@ bool Disassembler::load_library() { p = strstr(p ? p : base, "jvm"); if (p != NULL) jvm_offset = p - base; } +#endif // Find the disassembler shared library. // Search for several paths derived from libjvm, in this order: // 1. /jre/lib///libhsdis-.so (for compatibility) diff --git a/hotspot/src/share/vm/compiler/methodMatcher.cpp b/hotspot/src/share/vm/compiler/methodMatcher.cpp index a8a342ec9b2..51d38c7caec 100644 --- a/hotspot/src/share/vm/compiler/methodMatcher.cpp +++ b/hotspot/src/share/vm/compiler/methodMatcher.cpp @@ -306,7 +306,7 @@ void MethodMatcher::parse_method_pattern(char*& line, const char*& error_msg, Me } } -bool MethodMatcher::matches(methodHandle method) const { +bool MethodMatcher::matches(const methodHandle& method) const { Symbol* class_name = method->method_holder()->name(); Symbol* method_name = method->name(); Symbol* signature = method->signature(); @@ -362,7 +362,7 @@ BasicMatcher* BasicMatcher::parse_method_pattern(char* line, const char*& error_ return bm; } -bool BasicMatcher::match(methodHandle method) { +bool BasicMatcher::match(const methodHandle& method) { for (BasicMatcher* current = this; current != NULL; current = current->next()) { if (current->matches(method)) { return true; @@ -391,7 +391,7 @@ InlineMatcher* InlineMatcher::parse_method_pattern(char* line, const char*& erro return im; } -bool InlineMatcher::match(methodHandle method, int inline_action) { +bool InlineMatcher::match(const methodHandle& method, int inline_action) { for (InlineMatcher* current = this; current != NULL; current = current->next()) { if (current->matches(method)) { return (current->_inline_action == inline_action); diff --git a/hotspot/src/share/vm/compiler/methodMatcher.hpp b/hotspot/src/share/vm/compiler/methodMatcher.hpp index 938a14b0a55..546af4d5ed7 100644 --- a/hotspot/src/share/vm/compiler/methodMatcher.hpp +++ b/hotspot/src/share/vm/compiler/methodMatcher.hpp @@ -60,7 +60,7 @@ class MethodMatcher : public CHeapObj { void init(Symbol* class_name, Mode class_mode, Symbol* method_name, Mode method_mode, Symbol* signature); static void parse_method_pattern(char*& line, const char*& error_msg, MethodMatcher* m); static void print_symbol(outputStream* st, Symbol* h, Mode mode); - bool matches(methodHandle method) const; + bool matches(const methodHandle& method) const; void print_base(outputStream* st); private: @@ -82,7 +82,7 @@ public: } static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg); - bool match(methodHandle method); + bool match(const methodHandle& method); void set_next(BasicMatcher* next) { _next = next; } BasicMatcher* next() { return _next; } @@ -113,7 +113,7 @@ private: public: static InlineMatcher* parse_method_pattern(char* line, const char*& error_msg); - bool match(methodHandle method, int inline_action); + bool match(const methodHandle& method, int inline_action); void print(outputStream* st); void set_next(InlineMatcher* next) { _next = next; } InlineMatcher* next() { return _next; } diff --git a/hotspot/src/share/vm/compiler/oopMap.hpp b/hotspot/src/share/vm/compiler/oopMap.hpp index 080f80d4825..5428f3bdee2 100644 --- a/hotspot/src/share/vm/compiler/oopMap.hpp +++ b/hotspot/src/share/vm/compiler/oopMap.hpp @@ -73,8 +73,8 @@ public: // Constructors OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); } - OopMapValue (VMReg reg, oop_types t) { set_reg_type(reg,t); } - OopMapValue (VMReg reg, oop_types t, VMReg reg2) { set_reg_type(reg,t); set_content_reg(reg2); } + OopMapValue (VMReg reg, oop_types t) { set_reg_type(reg, t); set_content_reg(VMRegImpl::Bad()); } + OopMapValue (VMReg reg, oop_types t, VMReg reg2) { set_reg_type(reg, t); set_content_reg(reg2); } OopMapValue (CompressedReadStream* stream) { read_from(stream); } // Archiving @@ -87,7 +87,7 @@ public: void read_from(CompressedReadStream* stream) { set_value(stream->read_int()); - if(is_callee_saved() || is_derived_oop()) { + if (is_callee_saved() || is_derived_oop()) { set_content_reg(VMRegImpl::as_VMReg(stream->read_int(), true)); } } diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp index d924ed27baf..933186d34fe 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp @@ -73,11 +73,7 @@ void CompactibleFreeListSpace::set_cms_values() { } // Constructor -CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, - MemRegion mr, bool use_adaptive_freelists, - FreeBlockDictionary::DictionaryChoice dictionaryChoice) : - _dictionaryChoice(dictionaryChoice), - _adaptive_freelists(use_adaptive_freelists), +CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr) : _bt(bs, mr), // free list locks are in the range of values taken by _lockRank // This range currently is [_leaf+2, _leaf+3] @@ -100,48 +96,17 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, "FreeChunk is larger than expected"); _bt.set_space(this); initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); - // We have all of "mr", all of which we place in the dictionary - // as one big chunk. We'll need to decide here which of several - // possible alternative dictionary implementations to use. For - // now the choice is easy, since we have only one working - // implementation, namely, the simple binary tree (splaying - // temporarily disabled). - switch (dictionaryChoice) { - case FreeBlockDictionary::dictionaryBinaryTree: - _dictionary = new AFLBinaryTreeDictionary(mr); - break; - case FreeBlockDictionary::dictionarySplayTree: - case FreeBlockDictionary::dictionarySkipList: - default: - warning("dictionaryChoice: selected option not understood; using" - " default BinaryTreeDictionary implementation instead."); - } + + _dictionary = new AFLBinaryTreeDictionary(mr); + assert(_dictionary != NULL, "CMS dictionary initialization"); // The indexed free lists are initially all empty and are lazily // filled in on demand. Initialize the array elements to NULL. initializeIndexedFreeListArray(); - // Not using adaptive free lists assumes that allocation is first - // from the linAB's. Also a cms perm gen which can be compacted - // has to have the klass's klassKlass allocated at a lower - // address in the heap than the klass so that the klassKlass is - // moved to its new location before the klass is moved. - // Set the _refillSize for the linear allocation blocks - if (!use_adaptive_freelists) { - FreeChunk* fc = _dictionary->get_chunk(mr.word_size(), - FreeBlockDictionary::atLeast); - // The small linAB initially has all the space and will allocate - // a chunk of any size. - HeapWord* addr = (HeapWord*) fc; - _smallLinearAllocBlock.set(addr, fc->size() , - 1024*SmallForLinearAlloc, fc->size()); - // Note that _unallocated_block is not updated here. - // Allocations from the linear allocation block should - // update it. - } else { - _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, - SmallForLinearAlloc); - } + _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, + SmallForLinearAlloc); + // CMSIndexedFreeListReplenish should be at least 1 CMSIndexedFreeListReplenish = MAX2((uintx)1, CMSIndexedFreeListReplenish); _promoInfo.setSpace(this); @@ -297,22 +262,7 @@ void CompactibleFreeListSpace::reset_after_compaction() { MemRegion mr(compaction_top(), end()); reset(mr); // Now refill the linear allocation block(s) if possible. - if (_adaptive_freelists) { - refillLinearAllocBlocksIfNeeded(); - } else { - // Place as much of mr in the linAB as we can get, - // provided it was big enough to go into the dictionary. - FreeChunk* fc = dictionary()->find_largest_dict(); - if (fc != NULL) { - assert(fc->size() == mr.word_size(), - "Why was the chunk broken up?"); - removeChunkFromDictionary(fc); - HeapWord* addr = (HeapWord*) fc; - _smallLinearAllocBlock.set(addr, fc->size() , - 1024*SmallForLinearAlloc, fc->size()); - // Note that _unallocated_block is not updated here. - } - } + refillLinearAllocBlocksIfNeeded(); } // Walks the entire dictionary, returning a coterminal @@ -445,8 +395,7 @@ void CompactibleFreeListSpace::print_on(outputStream* st) const { // dump_memory_block(_smallLinearAllocBlock->_ptr, 128); - st->print_cr(" _fitStrategy = %s, _adaptive_freelists = %s", - _fitStrategy?"true":"false", _adaptive_freelists?"true":"false"); + st->print_cr(" _fitStrategy = %s", BOOL_TO_STR(_fitStrategy)); } void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st) @@ -617,23 +566,9 @@ void CompactibleFreeListSpace::set_end(HeapWord* value) { // Now, take this new chunk and add it to the free blocks. // Note that the BOT has not yet been updated for this block. size_t newFcSize = pointer_delta(value, prevEnd); - // XXX This is REALLY UGLY and should be fixed up. XXX - if (!_adaptive_freelists && _smallLinearAllocBlock._ptr == NULL) { - // Mark the boundary of the new block in BOT - _bt.mark_block(prevEnd, value); - // put it all in the linAB - MutexLockerEx x(parDictionaryAllocLock(), - Mutex::_no_safepoint_check_flag); - _smallLinearAllocBlock._ptr = prevEnd; - _smallLinearAllocBlock._word_size = newFcSize; - repairLinearAllocBlock(&_smallLinearAllocBlock); - // Births of chunks put into a LinAB are not recorded. Births - // of chunks as they are allocated out of a LinAB are. - } else { - // Add the block to the free lists, if possible coalescing it - // with the last free block, and update the BOT and census data. - addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize); - } + // Add the block to the free lists, if possible coalescing it + // with the last free block, and update the BOT and census data. + addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize); } } } @@ -1177,11 +1112,7 @@ HeapWord* CompactibleFreeListSpace::allocate(size_t size) { assert(size == adjustObjectSize(size), "use adjustObjectSize() before calling into allocate()"); - if (_adaptive_freelists) { - res = allocate_adaptive_freelists(size); - } else { // non-adaptive free lists - res = allocate_non_adaptive_freelists(size); - } + res = allocate_adaptive_freelists(size); if (res != NULL) { // check that res does lie in this space! @@ -1203,27 +1134,6 @@ HeapWord* CompactibleFreeListSpace::allocate(size_t size) { return res; } -HeapWord* CompactibleFreeListSpace::allocate_non_adaptive_freelists(size_t size) { - HeapWord* res = NULL; - // try and use linear allocation for smaller blocks - if (size < _smallLinearAllocBlock._allocation_size_limit) { - // if successful, the following also adjusts block offset table - res = getChunkFromSmallLinearAllocBlock(size); - } - // Else triage to indexed lists for smaller sizes - if (res == NULL) { - if (size < SmallForDictionary) { - res = (HeapWord*) getChunkFromIndexedFreeList(size); - } else { - // else get it from the big dictionary; if even this doesn't - // work we are out of luck. - res = (HeapWord*)getChunkFromDictionaryExact(size); - } - } - - return res; -} - HeapWord* CompactibleFreeListSpace::allocate_adaptive_freelists(size_t size) { assert_lock_strong(freelistLock()); HeapWord* res = NULL; @@ -1281,9 +1191,6 @@ size_t CompactibleFreeListSpace::expansionSpaceRequired(size_t obj_size) const { // bigLAB or a smallLAB plus refilling a PromotionInfo object. MinChunkSize // is added because the dictionary may over-allocate to avoid fragmentation. size_t space = obj_size; - if (!_adaptive_freelists) { - space = MAX2(space, _smallLinearAllocBlock._refillSize); - } space += _promoInfo.refillSize() + 2 * MinChunkSize; return space; } @@ -1698,11 +1605,7 @@ CompactibleFreeListSpace::returnChunkToFreeList(FreeChunk* fc) { size_t size = fc->size(); _bt.verify_single_block((HeapWord*) fc, size); _bt.verify_not_unallocated((HeapWord*) fc, size); - if (_adaptive_freelists) { - _indexedFreeList[size].return_chunk_at_tail(fc); - } else { - _indexedFreeList[size].return_chunk_at_head(fc); - } + _indexedFreeList[size].return_chunk_at_tail(fc); #ifndef PRODUCT if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { _indexedFreeList[size].verify_stats(); @@ -1931,10 +1834,6 @@ CompactibleFreeListSpace::gc_prologue() { void CompactibleFreeListSpace::gc_epilogue() { assert_locked(); - if (PrintGCDetails && Verbose && !_adaptive_freelists) { - if (_smallLinearAllocBlock._word_size == 0) - warning("CompactibleFreeListSpace(epilogue):: Linear allocation failure"); - } assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); _promoInfo.stopTrackingPromotions(); repairLinearAllocationBlocks(); @@ -2060,13 +1959,6 @@ CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) { } } -// Support for concurrent collection policy decisions. -bool CompactibleFreeListSpace::should_concurrent_collect() const { - // In the future we might want to add in fragmentation stats -- - // including erosion of the "mountain" into this decision as well. - return !adaptive_freelists() && linearAllocationWouldFail(); -} - // Support for compaction void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) { scan_and_forward(this, cp); diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp index 52213970689..3cfc3a665f5 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp @@ -138,15 +138,13 @@ class CompactibleFreeListSpace: public CompactibleSpace { // Linear allocation blocks LinearAllocBlock _smallLinearAllocBlock; - FreeBlockDictionary::DictionaryChoice _dictionaryChoice; AFLBinaryTreeDictionary* _dictionary; // Pointer to dictionary for large size blocks // Indexed array for small size blocks AdaptiveFreeList _indexedFreeList[IndexSetSize]; // Allocation strategy - bool _fitStrategy; // Use best fit strategy - bool _adaptive_freelists; // Use adaptive freelists + bool _fitStrategy; // Use best fit strategy // This is an address close to the largest free chunk in the heap. // It is currently assumed to be at the end of the heap. Free @@ -204,10 +202,6 @@ class CompactibleFreeListSpace: public CompactibleSpace { // strategy that attempts to keep the needed number of chunks in each // indexed free lists. HeapWord* allocate_adaptive_freelists(size_t size); - // Allocate from the linear allocation buffers first. This allocation - // strategy assumes maximal coalescing can maintain chunks large enough - // to be used as linear allocation buffers. - HeapWord* allocate_non_adaptive_freelists(size_t size); // Gets a chunk from the linear allocation block (LinAB). If there // is not enough space in the LinAB, refills it. @@ -333,9 +327,7 @@ class CompactibleFreeListSpace: public CompactibleSpace { public: // Constructor - CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr, - bool use_adaptive_freelists, - FreeBlockDictionary::DictionaryChoice); + CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr); // Accessors bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; } FreeBlockDictionary* dictionary() const { return _dictionary; } @@ -349,8 +341,6 @@ class CompactibleFreeListSpace: public CompactibleSpace { // chunk exists, return NULL. FreeChunk* find_chunk_at_end(); - bool adaptive_freelists() const { return _adaptive_freelists; } - void set_collector(CMSCollector* collector) { _collector = collector; } // Support for parallelization of rescan and marking. @@ -536,9 +526,6 @@ class CompactibleFreeListSpace: public CompactibleSpace { void addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size, bool coalesced); - // Support for decisions regarding concurrent collection policy. - bool should_concurrent_collect() const; - // Support for compaction. void prepare_for_compaction(CompactPoint* cp); void adjust_pointers(); diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index d29415817b5..8771eec8de9 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -190,9 +190,7 @@ class CMSParGCThreadState: public CHeapObj { }; ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration( - ReservedSpace rs, size_t initial_byte_size, - CardTableRS* ct, bool use_adaptive_freelists, - FreeBlockDictionary::DictionaryChoice dictionaryChoice) : + ReservedSpace rs, size_t initial_byte_size, CardTableRS* ct) : CardGeneration(rs, initial_byte_size, ct), _dilatation_factor(((double)MinChunkSize)/((double)(CollectedHeap::min_fill_size()))), _did_compact(false) @@ -208,9 +206,7 @@ ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration( _numWordsAllocated = 0; ) - _cmsSpace = new CompactibleFreeListSpace(_bts, MemRegion(bottom, end), - use_adaptive_freelists, - dictionaryChoice); + _cmsSpace = new CompactibleFreeListSpace(_bts, MemRegion(bottom, end)); NOT_PRODUCT(debug_cms_space = _cmsSpace;) _cmsSpace->_old_gen = this; @@ -1312,13 +1308,6 @@ bool ConcurrentMarkSweepGeneration::should_concurrent_collect() const { } return true; } - if (_cmsSpace->should_concurrent_collect()) { - if (PrintGCDetails && Verbose) { - gclog_or_tty->print(" %s: collect because cmsSpace says so ", - short_name()); - } - return true; - } return false; } @@ -1553,9 +1542,7 @@ void CMSCollector::acquire_control_and_collect(bool full, do_compaction_work(clear_all_soft_refs); // Has the GC time limit been exceeded? - size_t max_eden_size = _young_gen->max_capacity() - - _young_gen->to()->capacity() - - _young_gen->from()->capacity(); + size_t max_eden_size = _young_gen->max_eden_size(); GCCause::Cause gc_cause = gch->gc_cause(); size_policy()->check_gc_overhead_limit(_young_gen->used(), _young_gen->eden()->used(), @@ -1766,9 +1753,8 @@ void CMSCollector::collect_in_background(GCCause::Cause cause) { MutexLockerEx hl(Heap_lock, safepoint_check); FreelistLocker fll(this); MutexLockerEx x(CGC_lock, safepoint_check); - if (_foregroundGCIsActive || !UseAsyncConcMarkSweepGC) { - // The foreground collector is active or we're - // not using asynchronous collections. Skip this + if (_foregroundGCIsActive) { + // The foreground collector is. Skip this // background collection. assert(!_foregroundGCShouldWait, "Should be clear"); return; @@ -1795,7 +1781,7 @@ void CMSCollector::collect_in_background(GCCause::Cause cause) { } // Used for PrintGC - size_t prev_used; + size_t prev_used = 0; if (PrintGC && Verbose) { prev_used = _cmsGen->used(); } @@ -5214,9 +5200,8 @@ void CMSCollector::do_remark_non_parallel() { verify_work_stacks_empty(); // Restore evacuated mark words, if any, used for overflow list links - if (!CMSOverflowEarlyRestoration) { - restore_preserved_marks_if_any(); - } + restore_preserved_marks_if_any(); + verify_overflow_empty(); } @@ -6186,17 +6171,8 @@ void MarkRefsIntoAndScanClosure::do_oop(oop obj) { assert(_mark_stack->isEmpty(), "post-condition (eager drainage)"); assert(_collector->overflow_list_is_empty(), "overflow list was drained above"); - // We could restore evacuated mark words, if any, used for - // overflow list links here because the overflow list is - // provably empty here. That would reduce the maximum - // size requirements for preserved_{oop,mark}_stack. - // But we'll just postpone it until we are all done - // so we can just stream through. - if (!_concurrent_precleaning && CMSOverflowEarlyRestoration) { - _collector->restore_preserved_marks_if_any(); - assert(_collector->no_preserved_marks(), "No preserved marks"); - } - assert(!CMSOverflowEarlyRestoration || _collector->no_preserved_marks(), + + assert(_collector->no_preserved_marks(), "All preserved marks should have been restored above"); } } @@ -7536,7 +7512,7 @@ void SweepClosure::do_already_free_chunk(FreeChunk* fc) { // free lists. if (CMSTestInFreeList && !fc->cantCoalesce()) { assert(_sp->verify_chunk_in_free_list(fc), - "free chunk should be in free lists"); + "free chunk should be in free lists"); } // a chunk that is already free, should not have been // marked in the bit map @@ -7550,57 +7526,8 @@ void SweepClosure::do_already_free_chunk(FreeChunk* fc) { // See the definition of cantCoalesce(). if (!fc->cantCoalesce()) { // This chunk can potentially be coalesced. - if (_sp->adaptive_freelists()) { - // All the work is done in - do_post_free_or_garbage_chunk(fc, size); - } else { // Not adaptive free lists - // this is a free chunk that can potentially be coalesced by the sweeper; - if (!inFreeRange()) { - // if the next chunk is a free block that can't be coalesced - // it doesn't make sense to remove this chunk from the free lists - FreeChunk* nextChunk = (FreeChunk*)(addr + size); - assert((HeapWord*)nextChunk <= _sp->end(), "Chunk size out of bounds?"); - if ((HeapWord*)nextChunk < _sp->end() && // There is another free chunk to the right ... - nextChunk->is_free() && // ... which is free... - nextChunk->cantCoalesce()) { // ... but can't be coalesced - // nothing to do - } else { - // Potentially the start of a new free range: - // Don't eagerly remove it from the free lists. - // No need to remove it if it will just be put - // back again. (Also from a pragmatic point of view - // if it is a free block in a region that is beyond - // any allocated blocks, an assertion will fail) - // Remember the start of a free run. - initialize_free_range(addr, true); - // end - can coalesce with next chunk - } - } else { - // the midst of a free range, we are coalescing - print_free_block_coalesced(fc); - if (CMSTraceSweeper) { - gclog_or_tty->print(" -- pick up free block " PTR_FORMAT " (" SIZE_FORMAT ")\n", p2i(fc), size); - } - // remove it from the free lists - _sp->removeFreeChunkFromFreeLists(fc); - set_lastFreeRangeCoalesced(true); - // If the chunk is being coalesced and the current free range is - // in the free lists, remove the current free range so that it - // will be returned to the free lists in its entirety - all - // the coalesced pieces included. - if (freeRangeInFreeLists()) { - FreeChunk* ffc = (FreeChunk*) freeFinger(); - assert(ffc->size() == pointer_delta(addr, freeFinger()), - "Size of free range is inconsistent with chunk size."); - if (CMSTestInFreeList) { - assert(_sp->verify_chunk_in_free_list(ffc), - "free range is not in free lists"); - } - _sp->removeFreeChunkFromFreeLists(ffc); - set_freeRangeInFreeLists(false); - } - } - } + // All the work is done in + do_post_free_or_garbage_chunk(fc, size); // Note that if the chunk is not coalescable (the else arm // below), we unconditionally flush, without needing to do // a "lookahead," as we do below. @@ -7626,46 +7553,11 @@ size_t SweepClosure::do_garbage_chunk(FreeChunk* fc) { HeapWord* const addr = (HeapWord*) fc; const size_t size = CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size()); - if (_sp->adaptive_freelists()) { - // Verify that the bit map has no bits marked between - // addr and purported end of just dead object. - _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size); + // Verify that the bit map has no bits marked between + // addr and purported end of just dead object. + _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size); + do_post_free_or_garbage_chunk(fc, size); - do_post_free_or_garbage_chunk(fc, size); - } else { - if (!inFreeRange()) { - // start of a new free range - assert(size > 0, "A free range should have a size"); - initialize_free_range(addr, false); - } else { - // this will be swept up when we hit the end of the - // free range - if (CMSTraceSweeper) { - gclog_or_tty->print(" -- pick up garbage " PTR_FORMAT " (" SIZE_FORMAT ")\n", p2i(fc), size); - } - // If the chunk is being coalesced and the current free range is - // in the free lists, remove the current free range so that it - // will be returned to the free lists in its entirety - all - // the coalesced pieces included. - if (freeRangeInFreeLists()) { - FreeChunk* ffc = (FreeChunk*)freeFinger(); - assert(ffc->size() == pointer_delta(addr, freeFinger()), - "Size of free range is inconsistent with chunk size."); - if (CMSTestInFreeList) { - assert(_sp->verify_chunk_in_free_list(ffc), - "free range is not in free lists"); - } - _sp->removeFreeChunkFromFreeLists(ffc); - set_freeRangeInFreeLists(false); - } - set_lastFreeRangeCoalesced(true); - } - // this will be swept up when we hit the end of the free range - - // Verify that the bit map has no bits marked between - // addr and purported end of just dead object. - _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size); - } assert(_limit >= addr + size, "A freshly garbage chunk can't possibly straddle over _limit"); if (inFreeRange()) lookahead_and_flush(fc, size); @@ -7727,7 +7619,6 @@ void SweepClosure::do_post_free_or_garbage_chunk(FreeChunk* fc, // do_post_free_or_garbage_chunk() should only be called in the case // of the adaptive free list allocator. const bool fcInFreeLists = fc->is_free(); - assert(_sp->adaptive_freelists(), "Should only be used in this case."); assert((HeapWord*)fc <= _limit, "sweep invariant"); if (CMSTestInFreeList && fcInFreeLists) { assert(_sp->verify_chunk_in_free_list(fc), "free chunk is not in free lists"); @@ -7739,7 +7630,7 @@ void SweepClosure::do_post_free_or_garbage_chunk(FreeChunk* fc, HeapWord* const fc_addr = (HeapWord*) fc; - bool coalesce; + bool coalesce = false; const size_t left = pointer_delta(fc_addr, freeFinger()); const size_t right = chunkSize; switch (FLSCoalescePolicy) { @@ -7783,10 +7674,10 @@ void SweepClosure::do_post_free_or_garbage_chunk(FreeChunk* fc, if (freeRangeInFreeLists()) { FreeChunk* const ffc = (FreeChunk*)freeFinger(); assert(ffc->size() == pointer_delta(fc_addr, freeFinger()), - "Size of free range is inconsistent with chunk size."); + "Size of free range is inconsistent with chunk size."); if (CMSTestInFreeList) { assert(_sp->verify_chunk_in_free_list(ffc), - "Chunk is not in free lists"); + "Chunk is not in free lists"); } _sp->coalDeath(ffc->size()); _sp->removeFreeChunkFromFreeLists(ffc); @@ -7860,7 +7751,7 @@ void SweepClosure::flush_cur_free_chunk(HeapWord* chunk, size_t size) { FreeChunk* fc = (FreeChunk*) chunk; fc->set_size(size); assert(!_sp->verify_chunk_in_free_list(fc), - "chunk should not be in free lists yet"); + "chunk should not be in free lists yet"); } if (CMSTraceSweeper) { gclog_or_tty->print_cr(" -- add free block " PTR_FORMAT " (" SIZE_FORMAT ") to free lists", diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp index c846cb48308..1f0be952fc5 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp @@ -1076,10 +1076,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { void assert_correct_size_change_locking(); public: - ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, - CardTableRS* ct, - bool use_adaptive_freelists, - FreeBlockDictionary::DictionaryChoice); + ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, CardTableRS* ct); // Accessors CMSCollector* collector() const { return _collector; } @@ -1121,12 +1118,6 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { // over-rides MemRegion used_region_at_save_marks() const; - // Does a "full" (forced) collection invoked on this generation collect - // the young generation as well? - virtual bool full_collects_young_generation() const { - return !ScavengeBeforeFullGC; - } - // Adjust quantities in the generation affected by // the compaction. void reset_after_compaction(); diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp index 807284c0edc..82f9e51a6b2 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp @@ -79,9 +79,6 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread { static void makeSurrogateLockerThread(TRAPS); static SurrogateLockerThread* slt() { return _slt; } - // Tester - bool is_ConcurrentGC_thread() const { return true; } - static void threads_do(ThreadClosure* tc); // Printing diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp index e2ff84ab5f8..4b259afeb1e 100644 --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp @@ -57,10 +57,6 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/stack.inline.hpp" -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable:4355 ) // 'this' : used in base member initializer list -#endif ParScanThreadState::ParScanThreadState(Space* to_space_, ParNewGeneration* young_gen_, Generation* old_gen_, @@ -104,9 +100,6 @@ ParScanThreadState::ParScanThreadState(Space* to_space_, _old_gen_closure.set_generation(old_gen_); _old_gen_root_closure.set_generation(old_gen_); } -#ifdef _MSC_VER -#pragma warning( pop ) -#endif void ParScanThreadState::record_survivor_plab(HeapWord* plab_start, size_t plab_word_size) { @@ -597,10 +590,6 @@ void ParNewGenTask::work(uint worker_id) { par_scan_state.evacuate_followers_closure().do_void(); } -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable:4355 ) // 'this' : used in base member initializer list -#endif ParNewGeneration::ParNewGeneration(ReservedSpace rs, size_t initial_byte_size) : DefNewGeneration(rs, initial_byte_size, "PCopy"), _overflow_list(NULL), @@ -643,9 +632,6 @@ ParNewGeneration::ParNewGeneration(ReservedSpace rs, size_t initial_byte_size) ParallelGCThreads, CHECK); } } -#ifdef _MSC_VER -#pragma warning( pop ) -#endif // ParNewGeneration:: ParKeepAliveClosure::ParKeepAliveClosure(ParScanWeakRefClosure* cl) : diff --git a/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp index a0a62181e89..dc262c25b7b 100644 --- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp +++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp @@ -138,7 +138,6 @@ class VM_GenCollectFullConcurrent: public VM_GC_Operation { : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */) { assert(FullGCCount_lock != NULL, "Error"); - assert(UseAsyncConcMarkSweepGC, "Else will hang caller"); } ~VM_GenCollectFullConcurrent() {} virtual VMOp_Type type() const { return VMOp_GenCollectFullConcurrent; } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp index ea67798bbb5..0e2f4dd4bb3 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp @@ -30,7 +30,8 @@ #include "runtime/java.hpp" ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) : - _threads(NULL), _n_threads(0), + _threads(NULL), + _sample_thread(NULL), _hot_card_cache(g1h) { // Ergonomically select initial concurrent refinement parameters @@ -58,12 +59,10 @@ ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEn return NULL; } cg1r->_n_worker_threads = thread_num(); - // We need one extra thread to do the young gen rset size sampling. - cg1r->_n_threads = cg1r->_n_worker_threads + 1; cg1r->reset_threshold_step(); - cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_threads, mtGC); + cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_worker_threads, mtGC); if (cg1r->_threads == NULL) { *ecode = JNI_ENOMEM; vm_shutdown_during_initialization("Could not allocate an array for ConcurrentG1RefineThread"); @@ -73,7 +72,7 @@ ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEn uint worker_id_offset = DirtyCardQueueSet::num_par_ids(); ConcurrentG1RefineThread *next = NULL; - for (uint i = cg1r->_n_threads - 1; i != UINT_MAX; i--) { + for (uint i = cg1r->_n_worker_threads - 1; i != UINT_MAX; i--) { ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(cg1r, next, refine_closure, worker_id_offset, i); assert(t != NULL, "Conc refine should have been created"); if (t->osthread() == NULL) { @@ -86,6 +85,14 @@ ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEn cg1r->_threads[i] = t; next = t; } + + cg1r->_sample_thread = new G1YoungRemSetSamplingThread(); + if (cg1r->_sample_thread->osthread() == NULL) { + *ecode = JNI_ENOMEM; + vm_shutdown_during_initialization("Could not create G1YoungRemSetSamplingThread"); + return NULL; + } + *ecode = JNI_OK; return cg1r; } @@ -103,44 +110,36 @@ void ConcurrentG1Refine::init(G1RegionToSpaceMapper* card_counts_storage) { } void ConcurrentG1Refine::stop() { - if (_threads != NULL) { - for (uint i = 0; i < _n_threads; i++) { - _threads[i]->stop(); - } + for (uint i = 0; i < _n_worker_threads; i++) { + _threads[i]->stop(); } + _sample_thread->stop(); } void ConcurrentG1Refine::reinitialize_threads() { reset_threshold_step(); - if (_threads != NULL) { - for (uint i = 0; i < _n_threads; i++) { - _threads[i]->initialize(); - } + for (uint i = 0; i < _n_worker_threads; i++) { + _threads[i]->initialize(); } } ConcurrentG1Refine::~ConcurrentG1Refine() { - if (_threads != NULL) { - for (uint i = 0; i < _n_threads; i++) { - delete _threads[i]; - } - FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads); + for (uint i = 0; i < _n_worker_threads; i++) { + delete _threads[i]; } + FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads); + + delete _sample_thread; } void ConcurrentG1Refine::threads_do(ThreadClosure *tc) { - if (_threads != NULL) { - for (uint i = 0; i < _n_threads; i++) { - tc->do_thread(_threads[i]); - } - } + worker_threads_do(tc); + tc->do_thread(_sample_thread); } void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) { - if (_threads != NULL) { - for (uint i = 0; i < worker_thread_num(); i++) { - tc->do_thread(_threads[i]); - } + for (uint i = 0; i < worker_thread_num(); i++) { + tc->do_thread(_threads[i]); } } @@ -149,12 +148,10 @@ uint ConcurrentG1Refine::thread_num() { } void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const { - for (uint i = 0; i < _n_threads; ++i) { + for (uint i = 0; i < _n_worker_threads; ++i) { _threads[i]->print_on(st); st->cr(); } -} - -ConcurrentG1RefineThread * ConcurrentG1Refine::sampling_thread() const { - return _threads[worker_thread_num()]; + _sample_thread->print_on(st); + st->cr(); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp index b10aa68f53b..0e5525f73c2 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_GC_G1_CONCURRENTG1REFINE_HPP #include "gc/g1/g1HotCardCache.hpp" +#include "gc/g1/g1YoungRemSetSamplingThread.hpp" #include "memory/allocation.hpp" #include "runtime/thread.hpp" #include "utilities/globalDefinitions.hpp" @@ -39,8 +40,9 @@ class G1RemSet; class DirtyCardQueue; class ConcurrentG1Refine: public CHeapObj { + G1YoungRemSetSamplingThread* _sample_thread; + ConcurrentG1RefineThread** _threads; - uint _n_threads; uint _n_worker_threads; /* * The value of the update buffer queue length falls into one of 3 zones: @@ -91,8 +93,8 @@ class ConcurrentG1Refine: public CHeapObj { // Iterate over all worker refinement threads void worker_threads_do(ThreadClosure * tc); - // The RS sampling thread - ConcurrentG1RefineThread * sampling_thread() const; + // The RS sampling thread has nothing to do with refinement, but is here for now. + G1YoungRemSetSamplingThread * sampling_thread() const { return _sample_thread; } static uint thread_num(); @@ -106,7 +108,6 @@ class ConcurrentG1Refine: public CHeapObj { int yellow_zone() const { return _yellow_zone; } int red_zone() const { return _red_zone; } - uint total_thread_num() const { return _n_threads; } uint worker_thread_num() const { return _n_worker_threads; } int thread_threshold_step() const { return _thread_threshold_step; } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index f652cf97d06..a65b0638a82 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -50,9 +50,8 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex // Each thread has its own monitor. The i-th thread is responsible for signaling // to thread i+1 if the number of buffers in the queue exceeds a threshold for this // thread. Monitors are also used to wake up the threads during termination. - // The 0th worker in notified by mutator threads and has a special monitor. - // The last worker is used for young gen rset size sampling. - if (worker_id > 0) { + // The 0th (primary) worker is notified by mutator threads and has a special monitor. + if (!is_primary()) { _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true, Monitor::_safepoint_check_never); } else { @@ -66,61 +65,11 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex } void ConcurrentG1RefineThread::initialize() { - if (_worker_id < cg1r()->worker_thread_num()) { - // Current thread activation threshold - _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), - cg1r()->yellow_zone()); - // A thread deactivates once the number of buffer reached a deactivation threshold - _deactivation_threshold = MAX2(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone()); - } else { - set_active(true); - } -} - -void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { - SuspendibleThreadSetJoiner sts_join; - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - G1CollectorPolicy* g1p = g1h->g1_policy(); - if (g1p->adaptive_young_list_length()) { - int regions_visited = 0; - g1h->young_list()->rs_length_sampling_init(); - while (g1h->young_list()->rs_length_sampling_more()) { - g1h->young_list()->rs_length_sampling_next(); - ++regions_visited; - - // we try to yield every time we visit 10 regions - if (regions_visited == 10) { - if (sts_join.should_yield()) { - sts_join.yield(); - // we just abandon the iteration - break; - } - regions_visited = 0; - } - } - - g1p->revise_young_list_target_length_if_necessary(); - } -} - -void ConcurrentG1RefineThread::run_young_rs_sampling() { - DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); - _vtime_start = os::elapsedVTime(); - while(!_should_terminate) { - sample_young_list_rs_lengths(); - - if (os::supports_vtime()) { - _vtime_accum = (os::elapsedVTime() - _vtime_start); - } else { - _vtime_accum = 0.0; - } - - MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); - if (_should_terminate) { - break; - } - _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefinementServiceIntervalMillis); - } + // Current thread activation threshold + _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), + cg1r()->yellow_zone()); + // A thread deactivates once the number of buffer reached a deactivation threshold + _deactivation_threshold = MAX2(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone()); } void ConcurrentG1RefineThread::wait_for_completed_buffers() { @@ -133,12 +82,12 @@ void ConcurrentG1RefineThread::wait_for_completed_buffers() { bool ConcurrentG1RefineThread::is_active() { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); - return _worker_id > 0 ? _active : dcqs.process_completed_buffers(); + return is_primary() ? dcqs.process_completed_buffers() : _active; } void ConcurrentG1RefineThread::activate() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); - if (_worker_id > 0) { + if (!is_primary()) { if (G1TraceConcRefinement) { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d", @@ -154,7 +103,7 @@ void ConcurrentG1RefineThread::activate() { void ConcurrentG1RefineThread::deactivate() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); - if (_worker_id > 0) { + if (!is_primary()) { if (G1TraceConcRefinement) { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d", @@ -171,25 +120,24 @@ void ConcurrentG1RefineThread::run() { initialize_in_thread(); wait_for_universe_init(); - if (_worker_id >= cg1r()->worker_thread_num()) { - run_young_rs_sampling(); - terminate(); - return; - } + run_service(); + terminate(); +} + +void ConcurrentG1RefineThread::run_service() { _vtime_start = os::elapsedVTime(); - while (!_should_terminate) { - DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + while (!_should_terminate) { // Wait for work wait_for_completed_buffers(); - if (_should_terminate) { break; } { SuspendibleThreadSetJoiner sts_join; + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); do { int curr_buffer_num = (int)dcqs.completed_buffers_num(); @@ -199,7 +147,7 @@ void ConcurrentG1RefineThread::run() { dcqs.set_completed_queue_padding(0); } - if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) { + if (!is_primary() && curr_buffer_num <= _deactivation_threshold) { // If the number of the buffer has fallen below our threshold // we should deactivate. The predecessor will reactivate this // thread should the number of the buffers cross the threshold again. @@ -225,8 +173,10 @@ void ConcurrentG1RefineThread::run() { _vtime_accum = 0.0; } } - assert(_should_terminate, "just checking"); - terminate(); + + if (G1TraceConcRefinement) { + gclog_or_tty->print_cr("G1-Refine-stop"); + } } void ConcurrentG1RefineThread::stop() { @@ -236,10 +186,7 @@ void ConcurrentG1RefineThread::stop() { _should_terminate = true; } - { - MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); - _monitor->notify(); - } + stop_service(); { MutexLockerEx mu(Terminator_lock); @@ -247,8 +194,9 @@ void ConcurrentG1RefineThread::stop() { Terminator_lock->wait(); } } - if (G1TraceConcRefinement) { - gclog_or_tty->print_cr("G1-Refine-stop"); - } } +void ConcurrentG1RefineThread::stop_service() { + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + _monitor->notify(); +} \ No newline at end of file diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp index cbaf3c3d782..5b6d3ed79d5 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp @@ -31,14 +31,14 @@ class CardTableEntryClosure; class ConcurrentG1Refine; -// The G1 Concurrent Refinement Thread (could be several in the future). - +// One or more G1 Concurrent Refinement Threads may be active if concurrent +// refinement is in progress. class ConcurrentG1RefineThread: public ConcurrentGCThread { friend class VMStructs; friend class G1CollectedHeap; double _vtime_start; // Initial virtual time. - double _vtime_accum; // Initial virtual time. + double _vtime_accum; // Accumulated virtual time. uint _worker_id; uint _worker_id_offset; @@ -59,8 +59,6 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread { // This thread deactivation threshold int _deactivation_threshold; - void sample_young_list_rs_lengths(); - void run_young_rs_sampling(); void wait_for_completed_buffers(); void set_active(bool x) { _active = x; } @@ -68,6 +66,11 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread { void activate(); void deactivate(); + bool is_primary() { return (_worker_id == 0); } + + void run_service(); + void stop_service(); + public: virtual void run(); // Constructor diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp index 2eea03ad5b3..4fed0ca353d 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp @@ -454,10 +454,6 @@ bool CMRootRegions::wait_until_scan_finished() { return true; } -#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away -#pragma warning( disable:4355 ) // 'this' : used in base member initializer list -#endif // _MSC_VER - uint ConcurrentMark::scale_parallel_threads(uint n_par_threads) { return MAX2((n_par_threads + 2) / 4, 1U); } @@ -509,19 +505,6 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev _count_card_bitmaps(NULL), _count_marked_bytes(NULL), _completed_initialization(false) { - CMVerboseLevel verbose_level = (CMVerboseLevel) G1MarkingVerboseLevel; - if (verbose_level < no_verbose) { - verbose_level = no_verbose; - } - if (verbose_level > high_verbose) { - verbose_level = high_verbose; - } - _verbose_level = verbose_level; - - if (verbose_low()) { - gclog_or_tty->print_cr("[global] init, heap start = " PTR_FORMAT ", " - "heap end = " PTR_FORMAT, p2i(_heap_start), p2i(_heap_end)); - } _markBitMap1.initialize(g1h->reserved_region(), prev_bitmap_storage); _markBitMap2.initialize(g1h->reserved_region(), next_bitmap_storage); @@ -706,10 +689,6 @@ void ConcurrentMark::reset() { // Reset all the marking data structures and any necessary flags reset_marking_state(); - if (verbose_low()) { - gclog_or_tty->print_cr("[global] resetting"); - } - // We do reset all of them, since different phases will use // different number of active threads. So, it's easiest to have all // of them ready. @@ -823,12 +802,8 @@ class CheckBitmapClearHRClosure : public HeapRegionClosure { // This closure can be called concurrently to the mutator, so we must make sure // that the result of the getNextMarkedWordAddress() call is compared to the // value passed to it as limit to detect any found bits. - // We can use the region's orig_end() for the limit and the comparison value - // as it always contains the "real" end of the region that never changes and - // has no side effects. - // Due to the latter, there can also be no problem with the compiler generating - // reloads of the orig_end() call. - HeapWord* end = r->orig_end(); + // end never changes in G1. + HeapWord* end = r->end(); return _bitmap->getNextMarkedWordAddress(r->bottom(), end) != end; } }; @@ -842,9 +817,7 @@ bool ConcurrentMark::nextMarkBitmapIsClear() { class NoteStartOfMarkHRClosure: public HeapRegionClosure { public: bool doHeapRegion(HeapRegion* r) { - if (!r->is_continues_humongous()) { - r->note_start_of_marking(); - } + r->note_start_of_marking(); return false; } }; @@ -918,11 +891,6 @@ void ConcurrentMark::checkpointRootsInitialPost() { void ConcurrentMark::enter_first_sync_barrier(uint worker_id) { bool barrier_aborted; - - if (verbose_low()) { - gclog_or_tty->print_cr("[%u] entering first barrier", worker_id); - } - { SuspendibleThreadSetLeaver sts_leave(concurrent()); barrier_aborted = !_first_overflow_barrier_sync.enter(); @@ -931,14 +899,6 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) { // at this point everyone should have synced up and not be doing any // more work - if (verbose_low()) { - if (barrier_aborted) { - gclog_or_tty->print_cr("[%u] aborted first barrier", worker_id); - } else { - gclog_or_tty->print_cr("[%u] leaving first barrier", worker_id); - } - } - if (barrier_aborted) { // If the barrier aborted we ignore the overflow condition and // just abort the whole marking phase as quickly as possible. @@ -974,26 +934,10 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) { } void ConcurrentMark::enter_second_sync_barrier(uint worker_id) { - bool barrier_aborted; - - if (verbose_low()) { - gclog_or_tty->print_cr("[%u] entering second barrier", worker_id); - } - - { - SuspendibleThreadSetLeaver sts_leave(concurrent()); - barrier_aborted = !_second_overflow_barrier_sync.enter(); - } + SuspendibleThreadSetLeaver sts_leave(concurrent()); + _second_overflow_barrier_sync.enter(); // at this point everything should be re-initialized and ready to go - - if (verbose_low()) { - if (barrier_aborted) { - gclog_or_tty->print_cr("[%u] aborted second barrier", worker_id); - } else { - gclog_or_tty->print_cr("[%u] leaving second barrier", worker_id); - } - } } #ifndef PRODUCT @@ -1332,22 +1276,10 @@ protected: // Takes a region that's not empty (i.e., it has at least one // live object in it and sets its corresponding bit on the region - // bitmap to 1. If the region is "starts humongous" it will also set - // to 1 the bits on the region bitmap that correspond to its - // associated "continues humongous" regions. + // bitmap to 1. void set_bit_for_region(HeapRegion* hr) { - assert(!hr->is_continues_humongous(), "should have filtered those out"); - BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index(); - if (!hr->is_starts_humongous()) { - // Normal (non-humongous) case: just set the bit. - _region_bm->par_at_put(index, true); - } else { - // Starts humongous case: calculate how many regions are part of - // this humongous region and then set the bit range. - BitMap::idx_t end_index = (BitMap::idx_t) hr->last_hc_index(); - _region_bm->par_at_put_range(index, end_index, true); - } + _region_bm->par_at_put(index, true); } public: @@ -1371,18 +1303,6 @@ public: _bm(bm), _region_marked_bytes(0) { } bool doHeapRegion(HeapRegion* hr) { - - if (hr->is_continues_humongous()) { - // We will ignore these here and process them when their - // associated "starts humongous" region is processed (see - // set_bit_for_heap_region()). Note that we cannot rely on their - // associated "starts humongous" region to have their bit set to - // 1 since, due to the region chunking in the parallel region - // iteration, a "continues humongous" region might be visited - // before its associated "starts humongous". - return false; - } - HeapWord* ntams = hr->next_top_at_mark_start(); HeapWord* start = hr->bottom(); @@ -1420,6 +1340,11 @@ public: // Add the size of this object to the number of marked bytes. marked_bytes += (size_t)obj_sz * HeapWordSize; + // This will happen if we are handling a humongous object that spans + // several heap regions. + if (obj_end > hr->end()) { + break; + } // Find the next marked object after this one. start = _bm->getNextMarkedWordAddress(obj_end, ntams); } @@ -1471,7 +1396,6 @@ class VerifyLiveObjectDataHRClosure: public HeapRegionClosure { CalcLiveObjectsClosure _calc_cl; BitMap* _region_bm; // Region BM to be verified BitMap* _card_bm; // Card BM to be verified - bool _verbose; // verbose output? BitMap* _exp_region_bm; // Expected Region BM values BitMap* _exp_card_bm; // Expected card BM values @@ -1483,28 +1407,16 @@ public: BitMap* region_bm, BitMap* card_bm, BitMap* exp_region_bm, - BitMap* exp_card_bm, - bool verbose) : + BitMap* exp_card_bm) : _g1h(g1h), _cm(g1h->concurrent_mark()), _calc_cl(_cm->nextMarkBitMap(), g1h, exp_region_bm, exp_card_bm), - _region_bm(region_bm), _card_bm(card_bm), _verbose(verbose), + _region_bm(region_bm), _card_bm(card_bm), _exp_region_bm(exp_region_bm), _exp_card_bm(exp_card_bm), _failures(0) { } int failures() const { return _failures; } bool doHeapRegion(HeapRegion* hr) { - if (hr->is_continues_humongous()) { - // We will ignore these here and process them when their - // associated "starts humongous" region is processed (see - // set_bit_for_heap_region()). Note that we cannot rely on their - // associated "starts humongous" region to have their bit set to - // 1 since, due to the region chunking in the parallel region - // iteration, a "continues humongous" region might be visited - // before its associated "starts humongous". - return false; - } - int failures = 0; // Call the CalcLiveObjectsClosure to walk the marking bitmap for @@ -1513,22 +1425,29 @@ public: bool res = _calc_cl.doHeapRegion(hr); assert(res == false, "should be continuing"); - MutexLockerEx x((_verbose ? ParGCRareEvent_lock : NULL), - Mutex::_no_safepoint_check_flag); - // Verify the marked bytes for this region. size_t exp_marked_bytes = _calc_cl.region_marked_bytes(); size_t act_marked_bytes = hr->next_marked_bytes(); - // We're not OK if expected marked bytes > actual marked bytes. It means - // we have missed accounting some objects during the actual marking. if (exp_marked_bytes > act_marked_bytes) { - if (_verbose) { - gclog_or_tty->print_cr("Region %u: marked bytes mismatch: " - "expected: " SIZE_FORMAT ", actual: " SIZE_FORMAT, - hr->hrm_index(), exp_marked_bytes, act_marked_bytes); + if (hr->is_starts_humongous()) { + // For start_humongous regions, the size of the whole object will be + // in exp_marked_bytes. + HeapRegion* region = hr; + int num_regions; + for (num_regions = 0; region != NULL; num_regions++) { + region = _g1h->next_region_in_humongous(region); + } + if ((num_regions-1) * HeapRegion::GrainBytes >= exp_marked_bytes) { + failures += 1; + } else if (num_regions * HeapRegion::GrainBytes < exp_marked_bytes) { + failures += 1; + } + } else { + // We're not OK if expected marked bytes > actual marked bytes. It means + // we have missed accounting some objects during the actual marking. + failures += 1; } - failures += 1; } // Verify the bit, for this region, in the actual and expected @@ -1540,12 +1459,6 @@ public: bool expected = _exp_region_bm->at(index); bool actual = _region_bm->at(index); if (expected && !actual) { - if (_verbose) { - gclog_or_tty->print_cr("Region %u: region bitmap mismatch: " - "expected: %s, actual: %s", - hr->hrm_index(), - BOOL_TO_STR(expected), BOOL_TO_STR(actual)); - } failures += 1; } @@ -1561,23 +1474,10 @@ public: actual = _card_bm->at(i); if (expected && !actual) { - if (_verbose) { - gclog_or_tty->print_cr("Region %u: card bitmap mismatch at " SIZE_FORMAT ": " - "expected: %s, actual: %s", - hr->hrm_index(), i, - BOOL_TO_STR(expected), BOOL_TO_STR(actual)); - } failures += 1; } } - if (failures > 0 && _verbose) { - gclog_or_tty->print_cr("Region " HR_FORMAT ", ntams: " PTR_FORMAT ", " - "marked_bytes: calc/actual " SIZE_FORMAT "/" SIZE_FORMAT, - HR_FORMAT_PARAMS(hr), p2i(hr->next_top_at_mark_start()), - _calc_cl.region_marked_bytes(), hr->next_marked_bytes()); - } - _failures += failures; // We could stop iteration over the heap when we @@ -1599,7 +1499,6 @@ protected: BitMap* _expected_card_bm; int _failures; - bool _verbose; HeapRegionClaimer _hrclaimer; @@ -1611,13 +1510,11 @@ public: _g1h(g1h), _cm(_g1h->concurrent_mark()), _actual_region_bm(region_bm), _actual_card_bm(card_bm), _expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm), - _failures(0), _verbose(false), + _failures(0), _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) { assert(VerifyDuringGC, "don't call this otherwise"); assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity"); assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity"); - - _verbose = _cm->verbose_medium(); } void work(uint worker_id) { @@ -1626,8 +1523,7 @@ public: VerifyLiveObjectDataHRClosure verify_cl(_g1h, _actual_region_bm, _actual_card_bm, _expected_region_bm, - _expected_card_bm, - _verbose); + _expected_card_bm); _g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer); @@ -1652,18 +1548,6 @@ class FinalCountDataUpdateClosure: public CMCountDataClosureBase { CMCountDataClosureBase(g1h, region_bm, card_bm) { } bool doHeapRegion(HeapRegion* hr) { - - if (hr->is_continues_humongous()) { - // We will ignore these here and process them when their - // associated "starts humongous" region is processed (see - // set_bit_for_heap_region()). Note that we cannot rely on their - // associated "starts humongous" region to have their bit set to - // 1 since, due to the region chunking in the parallel region - // iteration, a "continues humongous" region might be visited - // before its associated "starts humongous". - return false; - } - HeapWord* ntams = hr->next_top_at_mark_start(); HeapWord* top = hr->top(); @@ -1760,7 +1644,7 @@ public: const HeapRegionSetCount& humongous_regions_removed() { return _humongous_regions_removed; } bool doHeapRegion(HeapRegion *hr) { - if (hr->is_continues_humongous() || hr->is_archive()) { + if (hr->is_archive()) { return false; } // We use a claim value of zero here because all regions @@ -1772,7 +1656,6 @@ public: _freed_bytes += hr->used(); hr->set_containing_set(NULL); if (hr->is_humongous()) { - assert(hr->is_starts_humongous(), "we should only see starts humongous"); _humongous_regions_removed.increment(1u, hr->capacity()); _g1->free_humongous_region(hr, _local_cleanup_list, true); } else { @@ -2095,12 +1978,6 @@ class G1CMKeepAliveAndDrainClosure: public OopClosure { template void do_oop_work(T* p) { if (!_cm->has_overflown()) { oop obj = oopDesc::load_decode_heap_oop(p); - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[%u] we're looking at location " - "*" PTR_FORMAT " = " PTR_FORMAT, - _task->worker_id(), p2i(p), p2i((void*) obj)); - } - _task->deal_with_reference(obj); _ref_counter--; @@ -2129,10 +2006,6 @@ class G1CMKeepAliveAndDrainClosure: public OopClosure { } while (_task->has_aborted() && !_cm->has_overflown()); _ref_counter = _ref_counter_limit; } - } else { - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[%u] CM Overflow", _task->worker_id()); - } } } }; @@ -2156,11 +2029,6 @@ class G1CMDrainMarkingStackClosure: public VoidClosure { void do_void() { do { - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[%u] Drain: Calling do_marking_step - serial: %s", - _task->worker_id(), BOOL_TO_STR(_is_serial)); - } - // We call CMTask::do_marking_step() to completely drain the local // and global marking stacks of entries pushed by the 'keep alive' // oop closure (an instance of G1CMKeepAliveAndDrainClosure above). @@ -2436,7 +2304,7 @@ private: // circumspect about treating the argument as an object. void do_entry(void* entry) const { _task->increment_refs_reached(); - HeapRegion* hr = _g1h->heap_region_containing_raw(entry); + HeapRegion* hr = _g1h->heap_region_containing(entry); if (entry < hr->next_top_at_mark_start()) { // Until we get here, we don't know whether entry refers to a valid // object; it could instead have been a stale reference. @@ -2586,32 +2454,9 @@ ConcurrentMark::claim_region(uint worker_id) { while (finger < _heap_end) { assert(_g1h->is_in_g1_reserved(finger), "invariant"); - // Note on how this code handles humongous regions. In the - // normal case the finger will reach the start of a "starts - // humongous" (SH) region. Its end will either be the end of the - // last "continues humongous" (CH) region in the sequence, or the - // standard end of the SH region (if the SH is the only region in - // the sequence). That way claim_region() will skip over the CH - // regions. However, there is a subtle race between a CM thread - // executing this method and a mutator thread doing a humongous - // object allocation. The two are not mutually exclusive as the CM - // thread does not need to hold the Heap_lock when it gets - // here. So there is a chance that claim_region() will come across - // a free region that's in the progress of becoming a SH or a CH - // region. In the former case, it will either - // a) Miss the update to the region's end, in which case it will - // visit every subsequent CH region, will find their bitmaps - // empty, and do nothing, or - // b) Will observe the update of the region's end (in which case - // it will skip the subsequent CH regions). - // If it comes across a region that suddenly becomes CH, the - // scenario will be similar to b). So, the race between - // claim_region() and a humongous object allocation might force us - // to do a bit of unnecessary work (due to some unnecessary bitmap - // iterations) but it should not introduce and correctness issues. - HeapRegion* curr_region = _g1h->heap_region_containing_raw(finger); + HeapRegion* curr_region = _g1h->heap_region_containing(finger); - // Above heap_region_containing_raw may return NULL as we always scan claim + // Above heap_region_containing may return NULL as we always scan claim // until the end of the heap. In this case, just jump to the next region. HeapWord* end = curr_region != NULL ? curr_region->end() : finger + HeapRegion::GrainWords; @@ -2622,55 +2467,21 @@ ConcurrentMark::claim_region(uint worker_id) { HeapWord* bottom = curr_region->bottom(); HeapWord* limit = curr_region->next_top_at_mark_start(); - if (verbose_low()) { - gclog_or_tty->print_cr("[%u] curr_region = " PTR_FORMAT " " - "[" PTR_FORMAT ", " PTR_FORMAT "), " - "limit = " PTR_FORMAT, - worker_id, p2i(curr_region), p2i(bottom), p2i(end), p2i(limit)); - } - // notice that _finger == end cannot be guaranteed here since, // someone else might have moved the finger even further assert(_finger >= end, "the finger should have moved forward"); - if (verbose_low()) { - gclog_or_tty->print_cr("[%u] we were successful with region = " - PTR_FORMAT, worker_id, p2i(curr_region)); - } - if (limit > bottom) { - if (verbose_low()) { - gclog_or_tty->print_cr("[%u] region " PTR_FORMAT " is not empty, " - "returning it ", worker_id, p2i(curr_region)); - } return curr_region; } else { assert(limit == bottom, "the region limit should be at bottom"); - if (verbose_low()) { - gclog_or_tty->print_cr("[%u] region " PTR_FORMAT " is empty, " - "returning NULL", worker_id, p2i(curr_region)); - } // we return NULL and the caller should try calling // claim_region() again. return NULL; } } else { assert(_finger > finger, "the finger should have moved forward"); - if (verbose_low()) { - if (curr_region == NULL) { - gclog_or_tty->print_cr("[%u] found uncommitted region, moving finger, " - "global finger = " PTR_FORMAT ", " - "our finger = " PTR_FORMAT, - worker_id, p2i(_finger), p2i(finger)); - } else { - gclog_or_tty->print_cr("[%u] somebody else moved the finger, " - "global finger = " PTR_FORMAT ", " - "our finger = " PTR_FORMAT, - worker_id, p2i(_finger), p2i(finger)); - } - } - // read it again finger = _finger; } @@ -2721,16 +2532,9 @@ void ConcurrentMark::verify_no_cset_oops() { // Verify the global finger HeapWord* global_finger = finger(); if (global_finger != NULL && global_finger < _heap_end) { - // The global finger always points to a heap region boundary. We - // use heap_region_containing_raw() to get the containing region - // given that the global finger could be pointing to a free region - // which subsequently becomes continues humongous. If that - // happens, heap_region_containing() will return the bottom of the - // corresponding starts humongous region and the check below will - // not hold any more. // Since we always iterate over all regions, we might get a NULL HeapRegion // here. - HeapRegion* global_hr = _g1h->heap_region_containing_raw(global_finger); + HeapRegion* global_hr = _g1h->heap_region_containing(global_finger); guarantee(global_hr == NULL || global_finger == global_hr->bottom(), "global finger: " PTR_FORMAT " region: " HR_FORMAT, p2i(global_finger), HR_FORMAT_PARAMS(global_hr)); @@ -2743,7 +2547,7 @@ void ConcurrentMark::verify_no_cset_oops() { HeapWord* task_finger = task->finger(); if (task_finger != NULL && task_finger < _heap_end) { // See above note on the global finger verification. - HeapRegion* task_hr = _g1h->heap_region_containing_raw(task_finger); + HeapRegion* task_hr = _g1h->heap_region_containing(task_finger); guarantee(task_hr == NULL || task_finger == task_hr->bottom() || !task_hr->in_collection_set(), "task finger: " PTR_FORMAT " region: " HR_FORMAT, @@ -2771,17 +2575,6 @@ class AggregateCountDataHRClosure: public HeapRegionClosure { _cm_card_bm(cm_card_bm), _max_worker_id(max_worker_id) { } bool doHeapRegion(HeapRegion* hr) { - if (hr->is_continues_humongous()) { - // We will ignore these here and process them when their - // associated "starts humongous" region is processed. - // Note that we cannot rely on their associated - // "starts humongous" region to have their bit set to 1 - // since, due to the region chunking in the parallel region - // iteration, a "continues humongous" region might be visited - // before its associated "starts humongous". - return false; - } - HeapWord* start = hr->bottom(); HeapWord* limit = hr->next_top_at_mark_start(); HeapWord* end = hr->end(); @@ -2926,7 +2719,7 @@ void ConcurrentMark::clear_all_count_data() { } void ConcurrentMark::print_stats() { - if (verbose_stats()) { + if (G1MarkingVerboseLevel > 0) { gclog_or_tty->print_cr("---------------------------------------------------------------------"); for (size_t i = 0; i < _active_tasks; ++i) { _tasks[i]->print_stats(); @@ -3038,18 +2831,6 @@ bool ConcurrentMark::do_yield_check(uint worker_id) { } } -#ifndef PRODUCT -// for debugging purposes -void ConcurrentMark::print_finger() { - gclog_or_tty->print_cr("heap [" PTR_FORMAT ", " PTR_FORMAT "), global finger = " PTR_FORMAT, - p2i(_heap_start), p2i(_heap_end), p2i(_finger)); - for (uint i = 0; i < _max_worker_id; ++i) { - gclog_or_tty->print(" %u: " PTR_FORMAT, i, p2i(_tasks[i]->finger())); - } - gclog_or_tty->cr(); -} -#endif - // Closure for iteration over bitmaps class CMBitMapClosure : public BitMapClosure { private: @@ -3066,8 +2847,6 @@ public: HeapWord* addr = _nextMarkBitMap->offsetToHeapWord(offset); assert(_nextMarkBitMap->isMarked(addr), "invariant"); assert( addr < _cm->finger(), "invariant"); - - statsOnly( _task->increase_objs_found_on_bitmap() ); assert(addr >= _task->finger(), "invariant"); // We move that task's local finger along. @@ -3103,14 +2882,6 @@ G1CMOopClosure::G1CMOopClosure(G1CollectedHeap* g1h, void CMTask::setup_for_region(HeapRegion* hr) { assert(hr != NULL, "claim_region() should have filtered out NULL regions"); - assert(!hr->is_continues_humongous(), - "claim_region() should have filtered out continues humongous regions"); - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] setting up for region " PTR_FORMAT, - _worker_id, p2i(hr)); - } - _curr_region = hr; _finger = hr->bottom(); update_region_limit(); @@ -3122,11 +2893,6 @@ void CMTask::update_region_limit() { HeapWord* limit = hr->next_top_at_mark_start(); if (limit == bottom) { - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] found an empty region " - "[" PTR_FORMAT ", " PTR_FORMAT ")", - _worker_id, p2i(bottom), p2i(limit)); - } // The region was collected underneath our feet. // We set the finger to bottom to ensure that the bitmap // iteration that will follow this will not do anything. @@ -3155,10 +2921,6 @@ void CMTask::update_region_limit() { void CMTask::giveup_current_region() { assert(_curr_region != NULL, "invariant"); - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] giving up region " PTR_FORMAT, - _worker_id, p2i(_curr_region)); - } clear_region_fields(); } @@ -3181,11 +2943,6 @@ void CMTask::set_cm_oop_closure(G1CMOopClosure* cm_oop_closure) { void CMTask::reset(CMBitMap* nextMarkBitMap) { guarantee(nextMarkBitMap != NULL, "invariant"); - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] resetting", _worker_id); - } - _nextMarkBitMap = nextMarkBitMap; clear_region_fields(); @@ -3193,30 +2950,6 @@ void CMTask::reset(CMBitMap* nextMarkBitMap) { _elapsed_time_ms = 0.0; _termination_time_ms = 0.0; _termination_start_time_ms = 0.0; - -#if _MARKING_STATS_ - _aborted = 0; - _aborted_overflow = 0; - _aborted_cm_aborted = 0; - _aborted_yield = 0; - _aborted_timed_out = 0; - _aborted_satb = 0; - _aborted_termination = 0; - _steal_attempts = 0; - _steals = 0; - _local_pushes = 0; - _local_pops = 0; - _local_max_size = 0; - _objs_scanned = 0; - _global_pushes = 0; - _global_pops = 0; - _global_max_size = 0; - _global_transfers_to = 0; - _global_transfers_from = 0; - _regions_claimed = 0; - _objs_found_on_bitmap = 0; - _satb_buffers_processed = 0; -#endif // _MARKING_STATS_ } bool CMTask::should_exit_termination() { @@ -3257,42 +2990,16 @@ void CMTask::regular_clock_call() { // (2) If marking has been aborted for Full GC, then we also abort. if (_cm->has_aborted()) { set_has_aborted(); - statsOnly( ++_aborted_cm_aborted ); return; } double curr_time_ms = os::elapsedVTime() * 1000.0; - // (3) If marking stats are enabled, then we update the step history. -#if _MARKING_STATS_ - if (_words_scanned >= _words_scanned_limit) { - ++_clock_due_to_scanning; - } - if (_refs_reached >= _refs_reached_limit) { - ++_clock_due_to_marking; - } - - double last_interval_ms = curr_time_ms - _interval_start_time_ms; - _interval_start_time_ms = curr_time_ms; - _all_clock_intervals_ms.add(last_interval_ms); - - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] regular clock, interval = %1.2lfms, " - "scanned = " SIZE_FORMAT "%s, refs reached = " SIZE_FORMAT "%s", - _worker_id, last_interval_ms, - _words_scanned, - (_words_scanned >= _words_scanned_limit) ? " (*)" : "", - _refs_reached, - (_refs_reached >= _refs_reached_limit) ? " (*)" : ""); - } -#endif // _MARKING_STATS_ - // (4) We check whether we should yield. If we have to, then we abort. if (SuspendibleThreadSet::should_yield()) { // We should yield. To do this we abort the task. The caller is // responsible for yielding. set_has_aborted(); - statsOnly( ++_aborted_yield ); return; } @@ -3302,7 +3009,6 @@ void CMTask::regular_clock_call() { if (elapsed_time_ms > _time_target_ms) { set_has_aborted(); _has_timed_out = true; - statsOnly( ++_aborted_timed_out ); return; } @@ -3310,14 +3016,9 @@ void CMTask::regular_clock_call() { // buffers available for processing. If there are, we abort. SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); if (!_draining_satb_buffers && satb_mq_set.process_completed_buffers()) { - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] aborting to deal with pending SATB buffers", - _worker_id); - } // we do need to process SATB buffers, we'll abort and restart // the marking task to do so set_has_aborted(); - statsOnly( ++_aborted_satb ); return; } } @@ -3336,10 +3037,6 @@ void CMTask::decrease_limits() { // entries to/from the global stack). It basically tries to decrease the // scanning limit so that the clock is called earlier. - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] decreasing limits", _worker_id); - } - _words_scanned_limit = _real_words_scanned_limit - 3 * words_scanned_period / 4; _refs_reached_limit = _real_refs_reached_limit - @@ -3361,26 +3058,8 @@ void CMTask::move_entries_to_global_stack() { if (n > 0) { // we popped at least one entry from the local queue - statsOnly( ++_global_transfers_to; _local_pops += n ); - if (!_cm->mark_stack_push(buffer, n)) { - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] aborting due to global stack overflow", - _worker_id); - } set_has_aborted(); - } else { - // the transfer was successful - - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] pushed %d entries to the global stack", - _worker_id, n); - } - statsOnly( size_t tmp_size = _cm->mark_stack_size(); - if (tmp_size > _global_max_size) { - _global_max_size = tmp_size; - } - _global_pushes += n ); } } @@ -3398,24 +3077,12 @@ void CMTask::get_entries_from_global_stack() { "we should not pop more than the given limit"); if (n > 0) { // yes, we did actually pop at least one entry - - statsOnly( ++_global_transfers_from; _global_pops += n ); - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] popped %d entries from the global stack", - _worker_id, n); - } for (int i = 0; i < n; ++i) { bool success = _task_queue->push(buffer[i]); // We only call this when the local queue is empty or under a // given target limit. So, we do not expect this push to fail. assert(success, "invariant"); } - - statsOnly( size_t tmp_size = (size_t)_task_queue->size(); - if (tmp_size > _local_max_size) { - _local_max_size = tmp_size; - } - _local_pushes += n ); } // this operation was quite expensive, so decrease the limits @@ -3436,21 +3103,9 @@ void CMTask::drain_local_queue(bool partially) { } if (_task_queue->size() > target_size) { - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] draining local queue, target size = " SIZE_FORMAT, - _worker_id, target_size); - } - oop obj; bool ret = _task_queue->pop_local(obj); while (ret) { - statsOnly( ++_local_pops ); - - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] popped " PTR_FORMAT, _worker_id, - p2i((void*) obj)); - } - assert(_g1h->is_in_g1_reserved((HeapWord*) obj), "invariant" ); assert(!_g1h->is_on_master_free_list( _g1h->heap_region_containing((HeapWord*) obj)), "invariant"); @@ -3463,11 +3118,6 @@ void CMTask::drain_local_queue(bool partially) { ret = _task_queue->pop_local(obj); } } - - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] drained local queue, size = %u", - _worker_id, _task_queue->size()); - } } } @@ -3492,20 +3142,10 @@ void CMTask::drain_global_stack(bool partially) { } if (_cm->mark_stack_size() > target_size) { - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] draining global_stack, target size " SIZE_FORMAT, - _worker_id, target_size); - } - while (!has_aborted() && _cm->mark_stack_size() > target_size) { get_entries_from_global_stack(); drain_local_queue(partially); } - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] drained global stack, size = " SIZE_FORMAT, - _worker_id, _cm->mark_stack_size()); - } } } @@ -3529,10 +3169,6 @@ void CMTask::drain_satb_buffers() { // until we run out of buffers or we need to abort. while (!has_aborted() && satb_mq_set.apply_closure_to_completed_buffer(&satb_cl)) { - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id); - } - statsOnly( ++_satb_buffers_processed ); regular_clock_call(); } @@ -3557,34 +3193,6 @@ void CMTask::print_stats() { _step_times_ms.sd()); gclog_or_tty->print_cr(" max = %1.2lfms, total = %1.2lfms", _step_times_ms.maximum(), _step_times_ms.sum()); - -#if _MARKING_STATS_ - gclog_or_tty->print_cr(" Clock Intervals (cum): num = %d, avg = %1.2lfms, sd = %1.2lfms", - _all_clock_intervals_ms.num(), _all_clock_intervals_ms.avg(), - _all_clock_intervals_ms.sd()); - gclog_or_tty->print_cr(" max = %1.2lfms, total = %1.2lfms", - _all_clock_intervals_ms.maximum(), - _all_clock_intervals_ms.sum()); - gclog_or_tty->print_cr(" Clock Causes (cum): scanning = " SIZE_FORMAT ", marking = " SIZE_FORMAT, - _clock_due_to_scanning, _clock_due_to_marking); - gclog_or_tty->print_cr(" Objects: scanned = " SIZE_FORMAT ", found on the bitmap = " SIZE_FORMAT, - _objs_scanned, _objs_found_on_bitmap); - gclog_or_tty->print_cr(" Local Queue: pushes = " SIZE_FORMAT ", pops = " SIZE_FORMAT ", max size = " SIZE_FORMAT, - _local_pushes, _local_pops, _local_max_size); - gclog_or_tty->print_cr(" Global Stack: pushes = " SIZE_FORMAT ", pops = " SIZE_FORMAT ", max size = " SIZE_FORMAT, - _global_pushes, _global_pops, _global_max_size); - gclog_or_tty->print_cr(" transfers to = " SIZE_FORMAT ", transfers from = " SIZE_FORMAT, - _global_transfers_to,_global_transfers_from); - gclog_or_tty->print_cr(" Regions: claimed = " SIZE_FORMAT, _regions_claimed); - gclog_or_tty->print_cr(" SATB buffers: processed = " SIZE_FORMAT, _satb_buffers_processed); - gclog_or_tty->print_cr(" Steals: attempts = " SIZE_FORMAT ", successes = " SIZE_FORMAT, - _steal_attempts, _steals); - gclog_or_tty->print_cr(" Aborted: " SIZE_FORMAT ", due to", _aborted); - gclog_or_tty->print_cr(" overflow: " SIZE_FORMAT ", global abort: " SIZE_FORMAT ", yield: " SIZE_FORMAT, - _aborted_overflow, _aborted_cm_aborted, _aborted_yield); - gclog_or_tty->print_cr(" time out: " SIZE_FORMAT ", SATB: " SIZE_FORMAT ", termination: " SIZE_FORMAT, - _aborted_timed_out, _aborted_satb, _aborted_termination); -#endif // _MARKING_STATS_ } bool ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, oop& obj) { @@ -3727,7 +3335,6 @@ void CMTask::do_marking_step(double time_target_ms, _claimed = true; _start_time_ms = os::elapsedVTime() * 1000.0; - statsOnly( _interval_start_time_ms = _start_time_ms ); // If do_stealing is true then do_marking_step will attempt to // steal work from the other CMTasks. It only makes sense to @@ -3751,12 +3358,6 @@ void CMTask::do_marking_step(double time_target_ms, ++_calls; - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] >>>>>>>>>> START, call = %d, " - "target = %1.2lfms >>>>>>>>>>", - _worker_id, _calls, _time_target_ms); - } - // Set up the bitmap and oop closures. Anything that uses them is // eventually called from this method, so it is OK to allocate these // statically. @@ -3801,14 +3402,6 @@ void CMTask::do_marking_step(double time_target_ms, // fresh region, _finger points to start(). MemRegion mr = MemRegion(_finger, _region_limit); - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] we're scanning part " - "[" PTR_FORMAT ", " PTR_FORMAT ") " - "of region " HR_FORMAT, - _worker_id, p2i(_finger), p2i(_region_limit), - HR_FORMAT_PARAMS(_curr_region)); - } - assert(!_curr_region->is_humongous() || mr.start() == _curr_region->bottom(), "humongous regions should go around loop once only"); @@ -3881,20 +3474,9 @@ void CMTask::do_marking_step(double time_target_ms, assert(_curr_region == NULL, "invariant"); assert(_finger == NULL, "invariant"); assert(_region_limit == NULL, "invariant"); - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] trying to claim a new region", _worker_id); - } HeapRegion* claimed_region = _cm->claim_region(_worker_id); if (claimed_region != NULL) { // Yes, we managed to claim one - statsOnly( ++_regions_claimed ); - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] we successfully claimed " - "region " PTR_FORMAT, - _worker_id, p2i(claimed_region)); - } - setup_for_region(claimed_region); assert(_curr_region == claimed_region, "invariant"); } @@ -3917,11 +3499,6 @@ void CMTask::do_marking_step(double time_target_ms, // tasks might be pushing objects to it concurrently. assert(_cm->out_of_regions(), "at this point we should be out of regions"); - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] all regions claimed", _worker_id); - } - // Try to reduce the number of available SATB buffers so that // remark has less work to do. drain_satb_buffers(); @@ -3941,23 +3518,9 @@ void CMTask::do_marking_step(double time_target_ms, // tasks might be pushing objects to it concurrently. assert(_cm->out_of_regions() && _task_queue->size() == 0, "only way to reach here"); - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] starting to steal", _worker_id); - } - while (!has_aborted()) { oop obj; - statsOnly( ++_steal_attempts ); - if (_cm->try_stealing(_worker_id, &_hash_seed, obj)) { - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] stolen " PTR_FORMAT " successfully", - _worker_id, p2i((void*) obj)); - } - - statsOnly( ++_steals ); - assert(_nextMarkBitMap->isMarked((HeapWord*) obj), "any stolen object should be marked"); scan_object(obj); @@ -3989,11 +3552,6 @@ void CMTask::do_marking_step(double time_target_ms, // Separated the asserts so that we know which one fires. assert(_cm->out_of_regions(), "only way to reach here"); assert(_task_queue->size() == 0, "only way to reach here"); - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] starting termination protocol", _worker_id); - } - _termination_start_time_ms = os::elapsedVTime() * 1000.0; // The CMTask class also extends the TerminatorTerminator class, @@ -4028,21 +3586,10 @@ void CMTask::do_marking_step(double time_target_ms, guarantee(_task_queue->size() == 0, "only way to reach here"); guarantee(!_cm->has_overflown(), "only way to reach here"); guarantee(!_cm->mark_stack_overflow(), "only way to reach here"); - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] all tasks terminated", _worker_id); - } } else { // Apparently there's more work to do. Let's abort this task. It // will restart it and we can hopefully find more things to do. - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] apparently there is more work to do", - _worker_id); - } - set_has_aborted(); - statsOnly( ++_aborted_termination ); } } @@ -4057,9 +3604,6 @@ void CMTask::do_marking_step(double time_target_ms, if (has_aborted()) { // The task was aborted for some reason. - - statsOnly( ++_aborted ); - if (_has_timed_out) { double diff_ms = elapsed_time_ms - _time_target_ms; // Keep statistics of how well we did with respect to hitting @@ -4076,10 +3620,6 @@ void CMTask::do_marking_step(double time_target_ms, // what they are doing and re-initialize in a safe manner. We // will achieve this with the use of two barrier sync points. - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] detected overflow", _worker_id); - } - if (!is_serial) { // We only need to enter the sync barrier if being called // from a parallel context @@ -4091,8 +3631,6 @@ void CMTask::do_marking_step(double time_target_ms, // task 0 will clear the global data structures. } - statsOnly( ++_aborted_overflow ); - // We clear the local state of this task... clear_region_fields(); @@ -4104,22 +3642,6 @@ void CMTask::do_marking_step(double time_target_ms, // marking, everything has been re-initialized and we're // ready to restart. } - - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] <<<<<<<<<< ABORTING, target = %1.2lfms, " - "elapsed = %1.2lfms <<<<<<<<<<", - _worker_id, _time_target_ms, elapsed_time_ms); - if (_cm->has_aborted()) { - gclog_or_tty->print_cr("[%u] ========== MARKING ABORTED ==========", - _worker_id); - } - } - } else { - if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] <<<<<<<<<< FINISHED, target = %1.2lfms, " - "elapsed = %1.2lfms <<<<<<<<<<", - _worker_id, _time_target_ms, elapsed_time_ms); - } } _claimed = false; @@ -4143,9 +3665,6 @@ CMTask::CMTask(uint worker_id, guarantee(task_queue != NULL, "invariant"); guarantee(task_queues != NULL, "invariant"); - statsOnly( _clock_due_to_scanning = 0; - _clock_due_to_marking = 0 ); - _marking_step_diffs_ms.add(0.5); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc/g1/concurrentMark.hpp index 9dc0e87093f..d5f4fd71fe4 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.hpp @@ -244,30 +244,6 @@ public: bool should_force() PRODUCT_RETURN_( return false; ); }; -// this will enable a variety of different statistics per GC task -#define _MARKING_STATS_ 0 -// this will enable the higher verbose levels -#define _MARKING_VERBOSE_ 0 - -#if _MARKING_STATS_ -#define statsOnly(statement) \ -do { \ - statement ; \ -} while (0) -#else // _MARKING_STATS_ -#define statsOnly(statement) \ -do { \ -} while (0) -#endif // _MARKING_STATS_ - -typedef enum { - no_verbose = 0, // verbose turned off - stats_verbose, // only prints stats at the end of marking - low_verbose, // low verbose, mostly per region and per major event - medium_verbose, // a bit more detailed than low - high_verbose // per object verbose -} CMVerboseLevel; - class YoungList; // Root Regions are regions that are not empty at the beginning of a @@ -415,9 +391,6 @@ protected: // time of remark. volatile bool _concurrent_marking_in_progress; - // Verbose level - CMVerboseLevel _verbose_level; - // All of these times are in ms NumberSeq _init_times; NumberSeq _remark_times; @@ -746,31 +719,12 @@ public: bool has_aborted() { return _has_aborted; } - // This prints the global/local fingers. It is used for debugging. - NOT_PRODUCT(void print_finger();) - void print_summary_info(); void print_worker_threads_on(outputStream* st) const; void print_on_error(outputStream* st) const; - // The following indicate whether a given verbose level has been - // set. Notice that anything above stats is conditional to - // _MARKING_VERBOSE_ having been set to 1 - bool verbose_stats() { - return _verbose_level >= stats_verbose; - } - bool verbose_low() { - return _MARKING_VERBOSE_ && _verbose_level >= low_verbose; - } - bool verbose_medium() { - return _MARKING_VERBOSE_ && _verbose_level >= medium_verbose; - } - bool verbose_high() { - return _MARKING_VERBOSE_ && _verbose_level >= high_verbose; - } - // Liveness counting // Utility routine to set an exclusive range of cards on the given @@ -818,16 +772,13 @@ public: size_t* marked_bytes_array, BitMap* task_card_bm); - // Counts the given memory region in the task/worker counting - // data structures for the given worker id. - inline void count_region(MemRegion mr, HeapRegion* hr, uint worker_id); - // Counts the given object in the given task/worker counting // data structures. inline void count_object(oop obj, HeapRegion* hr, size_t* marked_bytes_array, - BitMap* task_card_bm); + BitMap* task_card_bm, + size_t word_size); // Attempts to mark the given object and, if successful, counts // the object in the given task/worker counting structures. @@ -969,43 +920,6 @@ private: size_t* _marked_bytes_array; BitMap* _card_bm; - // LOTS of statistics related with this task -#if _MARKING_STATS_ - NumberSeq _all_clock_intervals_ms; - double _interval_start_time_ms; - - size_t _aborted; - size_t _aborted_overflow; - size_t _aborted_cm_aborted; - size_t _aborted_yield; - size_t _aborted_timed_out; - size_t _aborted_satb; - size_t _aborted_termination; - - size_t _steal_attempts; - size_t _steals; - - size_t _clock_due_to_marking; - size_t _clock_due_to_scanning; - - size_t _local_pushes; - size_t _local_pops; - size_t _local_max_size; - size_t _objs_scanned; - - size_t _global_pushes; - size_t _global_pops; - size_t _global_max_size; - - size_t _global_transfers_to; - size_t _global_transfers_from; - - size_t _regions_claimed; - size_t _objs_found_on_bitmap; - - size_t _satb_buffers_processed; -#endif // _MARKING_STATS_ - // it updates the local fields after this task has claimed // a new region to scan void setup_for_region(HeapRegion* hr); @@ -1139,10 +1053,6 @@ public: // it prints statistics associated with this task void print_stats(); - -#if _MARKING_STATS_ - void increase_objs_found_on_bitmap() { ++_objs_found_on_bitmap; } -#endif // _MARKING_STATS_ }; // Class that's used to to print out per-region liveness diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp b/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp index 03bc56be7c5..c75f6898713 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp @@ -89,9 +89,7 @@ inline void ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, size_t region_size_bytes = mr.byte_size(); uint index = hr->hrm_index(); - assert(!hr->is_continues_humongous(), "should not be HC region"); assert(hr == g1h->heap_region_containing(start), "sanity"); - assert(hr == g1h->heap_region_containing(mr.last()), "sanity"); assert(marked_bytes_array != NULL, "pre-condition"); assert(task_card_bm != NULL, "pre-condition"); @@ -116,23 +114,23 @@ inline void ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, set_card_bitmap_range(task_card_bm, start_idx, end_idx, false /* is_par */); } -// Counts the given memory region in the task/worker counting -// data structures for the given worker id. -inline void ConcurrentMark::count_region(MemRegion mr, - HeapRegion* hr, - uint worker_id) { - size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); - BitMap* task_card_bm = count_card_bitmap_for(worker_id); - count_region(mr, hr, marked_bytes_array, task_card_bm); -} - // Counts the given object in the given task/worker counting data structures. inline void ConcurrentMark::count_object(oop obj, HeapRegion* hr, size_t* marked_bytes_array, - BitMap* task_card_bm) { - MemRegion mr((HeapWord*)obj, obj->size()); - count_region(mr, hr, marked_bytes_array, task_card_bm); + BitMap* task_card_bm, + size_t word_size) { + assert(!hr->is_continues_humongous(), "Cannot enter count_object with continues humongous"); + if (!hr->is_starts_humongous()) { + MemRegion mr((HeapWord*)obj, word_size); + count_region(mr, hr, marked_bytes_array, task_card_bm); + } else { + do { + MemRegion mr(hr->bottom(), hr->top()); + count_region(mr, hr, marked_bytes_array, task_card_bm); + hr = _g1h->next_region_in_humongous(hr); + } while (hr != NULL); + } } // Attempts to mark the given object and, if successful, counts @@ -141,10 +139,9 @@ inline bool ConcurrentMark::par_mark_and_count(oop obj, HeapRegion* hr, size_t* marked_bytes_array, BitMap* task_card_bm) { - HeapWord* addr = (HeapWord*)obj; - if (_nextMarkBitMap->parMark(addr)) { + if (_nextMarkBitMap->parMark((HeapWord*)obj)) { // Update the task specific count data for the object. - count_object(obj, hr, marked_bytes_array, task_card_bm); + count_object(obj, hr, marked_bytes_array, task_card_bm, obj->size()); return true; } return false; @@ -157,10 +154,10 @@ inline bool ConcurrentMark::par_mark_and_count(oop obj, size_t word_size, HeapRegion* hr, uint worker_id) { - HeapWord* addr = (HeapWord*)obj; - if (_nextMarkBitMap->parMark(addr)) { - MemRegion mr(addr, word_size); - count_region(mr, hr, worker_id); + if (_nextMarkBitMap->parMark((HeapWord*)obj)) { + size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); + BitMap* task_card_bm = count_card_bitmap_for(worker_id); + count_object(obj, hr, marked_bytes_array, task_card_bm, word_size); return true; } return false; @@ -242,19 +239,9 @@ inline void CMTask::push(oop obj) { assert(!_g1h->is_obj_ill(obj), "invariant"); assert(_nextMarkBitMap->isMarked(objAddr), "invariant"); - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] pushing " PTR_FORMAT, _worker_id, p2i((void*) obj)); - } - if (!_task_queue->push(obj)) { // The local task queue looks full. We need to push some entries // to the global stack. - - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] task queue overflow, " - "moving entries to the global stack", - _worker_id); - } move_entries_to_global_stack(); // this should succeed since, even if we overflow the global @@ -263,12 +250,6 @@ inline void CMTask::push(oop obj) { bool success = _task_queue->push(obj); assert(success, "invariant"); } - - statsOnly( size_t tmp_size = (size_t)_task_queue->size(); - if (tmp_size > _local_max_size) { - _local_max_size = tmp_size; - } - ++_local_pushes ); } inline bool CMTask::is_below_finger(oop obj, HeapWord* global_finger) const { @@ -306,18 +287,12 @@ inline void CMTask::process_grey_object(oop obj) { assert(scan || obj->is_typeArray(), "Skipping scan of grey non-typeArray"); assert(_nextMarkBitMap->isMarked((HeapWord*) obj), "invariant"); - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] processing grey object " PTR_FORMAT, - _worker_id, p2i((void*) obj)); - } - size_t obj_size = obj->size(); _words_scanned += obj_size; if (scan) { obj->oop_iterate(_cm_oop_closure); } - statsOnly( ++_objs_scanned ); check_limits(); } @@ -325,12 +300,6 @@ inline void CMTask::process_grey_object(oop obj) { inline void CMTask::make_reference_grey(oop obj, HeapRegion* hr) { if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) { - - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] marked object " PTR_FORMAT, - _worker_id, p2i(obj)); - } - // No OrderAccess:store_load() is needed. It is implicit in the // CAS done in CMBitMap::parMark() call in the routine above. HeapWord* global_finger = _cm->finger(); @@ -362,13 +331,6 @@ inline void CMTask::make_reference_grey(oop obj, HeapRegion* hr) { // references, and the metadata is built-in. process_grey_object(obj); } else { - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] below a finger (local: " PTR_FORMAT - ", global: " PTR_FORMAT ") pushing " - PTR_FORMAT " on mark stack", - _worker_id, p2i(_finger), - p2i(global_finger), p2i(obj)); - } push(obj); } } @@ -376,11 +338,6 @@ inline void CMTask::make_reference_grey(oop obj, HeapRegion* hr) { } inline void CMTask::deal_with_reference(oop obj) { - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] we're dealing with reference = " PTR_FORMAT, - _worker_id, p2i((void*) obj)); - } - increment_refs_reached(); HeapWord* objAddr = (HeapWord*) obj; @@ -391,7 +348,7 @@ inline void CMTask::deal_with_reference(oop obj) { // Only get the containing region if the object is not marked on the // bitmap (otherwise, it's a waste of time since we won't do // anything with it). - HeapRegion* hr = _g1h->heap_region_containing_raw(obj); + HeapRegion* hr = _g1h->heap_region_containing(obj); if (!hr->obj_allocated_since_next_marking(obj)) { make_reference_grey(obj, hr); } @@ -411,7 +368,7 @@ inline void ConcurrentMark::grayRoot(oop obj, size_t word_size, assert(obj != NULL, "pre-condition"); HeapWord* addr = (HeapWord*) obj; if (hr == NULL) { - hr = _g1h->heap_region_containing_raw(addr); + hr = _g1h->heap_region_containing(addr); } else { assert(hr->is_in(addr), "pre-condition"); } @@ -420,16 +377,6 @@ inline void ConcurrentMark::grayRoot(oop obj, size_t word_size, // header it's impossible to get back a HC region. assert(!hr->is_continues_humongous(), "sanity"); - // We cannot assert that word_size == obj->size() given that obj - // might not be in a consistent state (another thread might be in - // the process of copying it). So the best thing we can do is to - // assert that word_size is under an upper bound which is its - // containing region's capacity. - assert(word_size * HeapWordSize <= hr->capacity(), - "size: " SIZE_FORMAT " capacity: " SIZE_FORMAT " " HR_FORMAT, - word_size * HeapWordSize, hr->capacity(), - HR_FORMAT_PARAMS(hr)); - if (addr < hr->next_top_at_mark_start()) { if (!_nextMarkBitMap->isMarked(addr)) { par_mark_and_count(obj, word_size, hr, worker_id); diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp index 36dd7fc29bb..4884a7742fd 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -92,15 +92,31 @@ void ConcurrentMarkThread::cm_log(bool doit, bool join_sts, const char* fmt, ... } } +// Marking pauses can be scheduled flexibly, so we might delay marking to meet MMU. +void ConcurrentMarkThread::delay_to_keep_mmu(G1CollectorPolicy* g1_policy, bool remark) { + if (g1_policy->adaptive_young_list_length()) { + double now = os::elapsedTime(); + double prediction_ms = remark ? g1_policy->predict_remark_time_ms() + : g1_policy->predict_cleanup_time_ms(); + G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker(); + jlong sleep_time_ms = mmu_tracker->when_ms(now, prediction_ms); + os::sleep(this, sleep_time_ms, false); + } +} void ConcurrentMarkThread::run() { initialize_in_thread(); - _vtime_start = os::elapsedVTime(); wait_for_universe_init(); + run_service(); + + terminate(); +} + +void ConcurrentMarkThread::run_service() { + _vtime_start = os::elapsedVTime(); + G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1_policy = g1h->g1_policy(); - G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker(); - Thread *current_thread = Thread::current(); while (!_should_terminate) { // wait until started is set. @@ -141,12 +157,7 @@ void ConcurrentMarkThread::run() { double mark_end_sec = os::elapsedTime(); _vtime_mark_accum += (mark_end_time - cycle_start); if (!cm()->has_aborted()) { - if (g1_policy->adaptive_young_list_length()) { - double now = os::elapsedTime(); - double remark_prediction_ms = g1_policy->predict_remark_time_ms(); - jlong sleep_time_ms = mmu_tracker->when_ms(now, remark_prediction_ms); - os::sleep(current_thread, sleep_time_ms, false); - } + delay_to_keep_mmu(g1_policy, true /* remark */); cm_log(G1Log::fine(), true, "[GC concurrent-mark-end, %1.7lf secs]", mark_end_sec - mark_start_sec); @@ -167,12 +178,7 @@ void ConcurrentMarkThread::run() { _vtime_accum = (end_time - _vtime_start); if (!cm()->has_aborted()) { - if (g1_policy->adaptive_young_list_length()) { - double now = os::elapsedTime(); - double cleanup_prediction_ms = g1_policy->predict_cleanup_time_ms(); - jlong sleep_time_ms = mmu_tracker->when_ms(now, cleanup_prediction_ms); - os::sleep(current_thread, sleep_time_ms, false); - } + delay_to_keep_mmu(g1_policy, false /* cleanup */); CMCleanUp cl_cl(_cm); VM_CGC_Operation op(&cl_cl, "GC cleanup", false /* needs_pll */); @@ -272,9 +278,6 @@ void ConcurrentMarkThread::run() { g1h->register_concurrent_cycle_end(); } } - assert(_should_terminate, "just checking"); - - terminate(); } void ConcurrentMarkThread::stop() { @@ -283,10 +286,7 @@ void ConcurrentMarkThread::stop() { _should_terminate = true; } - { - MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag); - CGC_lock->notify_all(); - } + stop_service(); { MutexLockerEx ml(Terminator_lock); @@ -296,6 +296,11 @@ void ConcurrentMarkThread::stop() { } } +void ConcurrentMarkThread::stop_service() { + MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag); + CGC_lock->notify_all(); +} + void ConcurrentMarkThread::sleepBeforeNextCycle() { // We join here because we don't want to do the "shouldConcurrentMark()" // below while the world is otherwise stopped. diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp index afcb3f13e8f..13f34d676a9 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp @@ -27,11 +27,11 @@ #include "gc/shared/concurrentGCThread.hpp" -// The Concurrent Mark GC Thread (could be several in the future). -// This is copied from the Concurrent Mark Sweep GC Thread -// Still under construction. +// The Concurrent Mark GC Thread triggers the parallel CMConcurrentMarkingTasks +// as well as handling various marking cleanup. class ConcurrentMark; +class G1CollectorPolicy; class ConcurrentMarkThread: public ConcurrentGCThread { friend class VMStructs; @@ -57,6 +57,10 @@ class ConcurrentMarkThread: public ConcurrentGCThread { volatile State _state; void sleepBeforeNextCycle(); + void delay_to_keep_mmu(G1CollectorPolicy* g1_policy, bool remark); + + void run_service(); + void stop_service(); static SurrogateLockerThread* _slt; @@ -67,9 +71,9 @@ class ConcurrentMarkThread: public ConcurrentGCThread { static void makeSurrogateLockerThread(TRAPS); static SurrogateLockerThread* slt() { return _slt; } - // Total virtual time so far. + // Total virtual time so far for this thread and concurrent marking tasks. double vtime_accum(); - // Marking virtual time so far + // Marking virtual time so far this thread and concurrent marking tasks. double vtime_mark_accum(); ConcurrentMark* cm() { return _cm; } diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp index 94a60746a1f..15947fddf76 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp @@ -32,6 +32,18 @@ #include "runtime/safepoint.hpp" #include "runtime/thread.inline.hpp" +DirtyCardQueue::DirtyCardQueue(DirtyCardQueueSet* qset, bool permanent) : + // Dirty card queues are always active, so we create them with their + // active field set to true. + PtrQueue(qset, permanent, true /* active */) +{ } + +DirtyCardQueue::~DirtyCardQueue() { + if (!is_permanent()) { + flush(); + } +} + bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl, bool consume, uint worker_i) { @@ -40,7 +52,9 @@ bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl, res = apply_closure_to_buffer(cl, _buf, _index, _sz, consume, worker_i); - if (res && consume) _index = _sz; + if (res && consume) { + _index = _sz; + } } return res; } @@ -51,27 +65,27 @@ bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl, bool consume, uint worker_i) { if (cl == NULL) return true; - for (size_t i = index; i < sz; i += oopSize) { - int ind = byte_index_to_index((int)i); - jbyte* card_ptr = (jbyte*)buf[ind]; + size_t limit = byte_index_to_index(sz); + for (size_t i = byte_index_to_index(index); i < limit; ++i) { + jbyte* card_ptr = static_cast(buf[i]); if (card_ptr != NULL) { // Set the entry to null, so we don't do it again (via the test // above) if we reconsider this buffer. - if (consume) buf[ind] = NULL; - if (!cl->do_card_ptr(card_ptr, worker_i)) return false; + if (consume) { + buf[i] = NULL; + } + if (!cl->do_card_ptr(card_ptr, worker_i)) { + return false; + } } } return true; } -#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away -#pragma warning( disable:4355 ) // 'this' : used in base member initializer list -#endif // _MSC_VER - DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : PtrQueueSet(notify_when_complete), _mut_process_closure(NULL), - _shared_dirty_card_queue(this, true /*perm*/), + _shared_dirty_card_queue(this, true /* permanent */), _free_ids(NULL), _processed_buffers_mut(0), _processed_buffers_rs_thread(0) { @@ -83,13 +97,19 @@ uint DirtyCardQueueSet::num_par_ids() { return (uint)os::processor_count(); } -void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock, +void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, + Monitor* cbl_mon, + Mutex* fl_lock, int process_completed_threshold, int max_completed_queue, - Mutex* lock, PtrQueueSet* fl_owner) { + Mutex* lock, + DirtyCardQueueSet* fl_owner) { _mut_process_closure = cl; - PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, - max_completed_queue, fl_owner); + PtrQueueSet::initialize(cbl_mon, + fl_lock, + process_completed_threshold, + max_completed_queue, + fl_owner); set_buffer_size(G1UpdateBufferSize); _shared_dirty_card_queue.set_lock(lock); _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon); @@ -103,7 +123,7 @@ void DirtyCardQueueSet::iterate_closure_all_threads(CardTableEntryClosure* cl, bool consume, uint worker_i) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); - for(JavaThread* t = Threads::first(); t; t = t->next()) { + for (JavaThread* t = Threads::first(); t; t = t->next()) { bool b = t->dirty_card_queue().apply_closure(cl, consume); guarantee(b, "Should not be interrupted."); } @@ -160,8 +180,7 @@ bool DirtyCardQueueSet::mut_process_buffer(void** buf) { } -BufferNode* -DirtyCardQueueSet::get_completed_buffer(int stop_at) { +BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) { BufferNode* nd = NULL; MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); @@ -178,14 +197,13 @@ DirtyCardQueueSet::get_completed_buffer(int stop_at) { _n_completed_buffers--; assert(_n_completed_buffers >= 0, "Invariant"); } - debug_only(assert_completed_buffer_list_len_correct_locked()); + DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); return nd; } -bool DirtyCardQueueSet:: -apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - uint worker_i, - BufferNode* nd) { +bool DirtyCardQueueSet::apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, + uint worker_i, + BufferNode* nd) { if (nd != NULL) { void **buf = BufferNode::make_buffer_from_node(nd); size_t index = nd->index(); @@ -259,7 +277,7 @@ void DirtyCardQueueSet::clear() { } _n_completed_buffers = 0; _completed_buffers_tail = NULL; - debug_only(assert_completed_buffer_list_len_correct_locked()); + DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); } while (buffers_to_delete != NULL) { BufferNode* nd = buffers_to_delete; @@ -291,10 +309,11 @@ void DirtyCardQueueSet::concatenate_logs() { for (JavaThread* t = Threads::first(); t; t = t->next()) { DirtyCardQueue& dcq = t->dirty_card_queue(); if (dcq.size() != 0) { - void **buf = t->dirty_card_queue().get_buf(); + void** buf = dcq.get_buf(); // We must NULL out the unused entries, then enqueue. - for (size_t i = 0; i < t->dirty_card_queue().get_index(); i += oopSize) { - buf[PtrQueue::byte_index_to_index((int)i)] = NULL; + size_t limit = dcq.byte_index_to_index(dcq.get_index()); + for (size_t i = 0; i < limit; ++i) { + buf[i] = NULL; } enqueue_complete_buffer(dcq.get_buf(), dcq.get_index()); dcq.reinitialize(); diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp index 84a02b8f1d2..86fc438b71e 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp @@ -29,6 +29,7 @@ #include "memory/allocation.hpp" class FreeIdSet; +class DirtyCardQueueSet; // A closure class for processing card table entries. Note that we don't // require these closure objects to be stack-allocated. @@ -42,14 +43,11 @@ public: // A ptrQueue whose elements are "oops", pointers to object heads. class DirtyCardQueue: public PtrQueue { public: - DirtyCardQueue(PtrQueueSet* qset_, bool perm = false) : - // Dirty card queues are always active, so we create them with their - // active field set to true. - PtrQueue(qset_, perm, true /* active */) { } + DirtyCardQueue(DirtyCardQueueSet* qset, bool permanent = false); // Flush before destroying; queue may be used to capture pending work while // doing something else, with auto-flush on completion. - ~DirtyCardQueue() { if (!is_permanent()) flush(); } + ~DirtyCardQueue(); // Process queue entries and release resources. void flush() { flush_impl(); } @@ -72,7 +70,6 @@ public: bool consume = true, uint worker_i = 0); void **get_buf() { return _buf;} - void set_buf(void **buf) {_buf = buf;} size_t get_index() { return _index;} void reinitialize() { _buf = 0; _sz = 0; _index = 0;} }; @@ -101,10 +98,13 @@ class DirtyCardQueueSet: public PtrQueueSet { public: DirtyCardQueueSet(bool notify_when_complete = true); - void initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock, + void initialize(CardTableEntryClosure* cl, + Monitor* cbl_mon, + Mutex* fl_lock, int process_completed_threshold, int max_completed_queue, - Mutex* lock, PtrQueueSet* fl_owner = NULL); + Mutex* lock, + DirtyCardQueueSet* fl_owner = NULL); // The number of parallel ids that can be claimed to allow collector or // mutator threads to do card-processing work. diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp index f298798430e..9a63b618d8b 100644 --- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp @@ -110,9 +110,6 @@ void G1DefaultAllocator::release_gc_alloc_regions(EvacuationInfo& evacuation_inf if (_retained_old_gc_alloc_region != NULL) { _retained_old_gc_alloc_region->record_retained_region(); } - - _g1h->alloc_buffer_stats(InCSetState::Young)->adjust_desired_plab_sz(); - _g1h->alloc_buffer_stats(InCSetState::Old)->adjust_desired_plab_sz(); } void G1DefaultAllocator::abandon_gc_alloc_regions() { diff --git a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp index 276260534c3..801e4c9f5cf 100644 --- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp +++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp @@ -499,18 +499,14 @@ HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() { return _next_offset_threshold; } -void -G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) { - assert(new_top <= _end, "_end should have already been updated"); - +void G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* obj_top) { // The first BOT entry should have offset 0. reset_bot(); - alloc_block(_bottom, new_top); + alloc_block(_bottom, obj_top); } #ifndef PRODUCT -void -G1BlockOffsetArrayContigSpace::print_on(outputStream* out) { +void G1BlockOffsetArrayContigSpace::print_on(outputStream* out) { G1BlockOffsetArray::print_on(out); out->print_cr(" next offset threshold: " PTR_FORMAT, p2i(_next_offset_threshold)); out->print_cr(" next offset index: " SIZE_FORMAT, _next_offset_index); diff --git a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp index 095054b376e..7592dec864d 100644 --- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp +++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp @@ -361,17 +361,18 @@ class G1BlockOffsetArrayContigSpace: public G1BlockOffsetArray { // implementation, that's true because NULL is represented as 0, and thus // never exceeds the "_next_offset_threshold". void alloc_block(HeapWord* blk_start, HeapWord* blk_end) { - if (blk_end > _next_offset_threshold) + if (blk_end > _next_offset_threshold) { alloc_block_work1(blk_start, blk_end); + } } void alloc_block(HeapWord* blk, size_t size) { - alloc_block(blk, blk+size); + alloc_block(blk, blk+size); } HeapWord* block_start_unsafe(const void* addr); HeapWord* block_start_unsafe_const(const void* addr) const; - void set_for_starts_humongous(HeapWord* new_top); + void set_for_starts_humongous(HeapWord* obj_top); virtual void print_on(outputStream* out) PRODUCT_RETURN; }; diff --git a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp index ac854a4e70c..202d4e5bb94 100644 --- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp @@ -123,7 +123,6 @@ G1BlockOffsetArray::block_at_or_preceding(const void* addr, // to go back by. size_t n_cards_back = BlockOffsetArray::entry_to_cards_back(offset); q -= (N_words * n_cards_back); - assert(q >= gsp()->bottom(), "Went below bottom!"); index -= n_cards_back; offset = _array->offset_array(index); } diff --git a/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp b/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp index f0593f25943..c0ac7a8d557 100644 --- a/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp @@ -36,7 +36,7 @@ void G1CodeBlobClosure::HeapRegionGatheringOopClosure::do_oop_work(T* p) { T oop_or_narrowoop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(oop_or_narrowoop)) { oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop); - HeapRegion* hr = _g1h->heap_region_containing_raw(o); + HeapRegion* hr = _g1h->heap_region_containing(o); assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in collection set then evacuation failed and nm must already be in the remset"); hr->add_strong_code_root(_nm); } diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 4b36a61ff68..5b779becfee 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -320,12 +320,8 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first, // The header of the new object will be placed at the bottom of // the first region. HeapWord* new_obj = first_hr->bottom(); - // This will be the new end of the first region in the series that - // should also match the end of the last region in the series. - HeapWord* new_end = new_obj + word_size_sum; - // This will be the new top of the first region that will reflect - // this allocation. - HeapWord* new_top = new_obj + word_size; + // This will be the new top of the new object. + HeapWord* obj_top = new_obj + word_size; // First, we need to zero the header of the space that we will be // allocating. When we update top further down, some refinement @@ -346,7 +342,7 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first, // will also update the BOT covering all the regions to reflect // that there is a single object that starts at the bottom of the // first region. - first_hr->set_starts_humongous(new_top, new_end); + first_hr->set_starts_humongous(obj_top); first_hr->set_allocation_context(context); // Then, if there are any, we will set up the "continues // humongous" regions. @@ -356,9 +352,6 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first, hr->set_continues_humongous(first_hr); hr->set_allocation_context(context); } - // If we have "continues humongous" regions (hr != NULL), then the - // end of the last one should match new_end. - assert(hr == NULL || hr->end() == new_end, "sanity"); // Up to this point no concurrent thread would have been able to // do any scanning on any region in this series. All the top @@ -371,58 +364,39 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first, // Now that the BOT and the object header have been initialized, // we can update top of the "starts humongous" region. - assert(first_hr->bottom() < new_top && new_top <= first_hr->end(), - "new_top should be in this region"); - first_hr->set_top(new_top); + first_hr->set_top(MIN2(first_hr->end(), obj_top)); if (_hr_printer.is_active()) { - HeapWord* bottom = first_hr->bottom(); - HeapWord* end = first_hr->orig_end(); - if ((first + 1) == last) { - // the series has a single humongous region - _hr_printer.alloc(G1HRPrinter::SingleHumongous, first_hr, new_top); - } else { - // the series has more than one humongous regions - _hr_printer.alloc(G1HRPrinter::StartsHumongous, first_hr, end); - } + _hr_printer.alloc(G1HRPrinter::StartsHumongous, first_hr, first_hr->top()); } // Now, we will update the top fields of the "continues humongous" - // regions. The reason we need to do this is that, otherwise, - // these regions would look empty and this will confuse parts of - // G1. For example, the code that looks for a consecutive number - // of empty regions will consider them empty and try to - // re-allocate them. We can extend is_empty() to also include - // !is_continues_humongous(), but it is easier to just update the top - // fields here. The way we set top for all regions (i.e., top == - // end for all regions but the last one, top == new_top for the - // last one) is actually used when we will free up the humongous - // region in free_humongous_region(). + // regions. hr = NULL; for (uint i = first + 1; i < last; ++i) { hr = region_at(i); if ((i + 1) == last) { // last continues humongous region - assert(hr->bottom() < new_top && new_top <= hr->end(), + assert(hr->bottom() < obj_top && obj_top <= hr->end(), "new_top should fall on this region"); - hr->set_top(new_top); - _hr_printer.alloc(G1HRPrinter::ContinuesHumongous, hr, new_top); + hr->set_top(obj_top); + _hr_printer.alloc(G1HRPrinter::ContinuesHumongous, hr, obj_top); } else { // not last one - assert(new_top > hr->end(), "new_top should be above this region"); + assert(obj_top > hr->end(), "obj_top should be above this region"); hr->set_top(hr->end()); _hr_printer.alloc(G1HRPrinter::ContinuesHumongous, hr, hr->end()); } } - // If we have continues humongous regions (hr != NULL), then the - // end of the last one should match new_end and its top should - // match new_top. - assert(hr == NULL || - (hr->end() == new_end && hr->top() == new_top), "sanity"); + // If we have continues humongous regions (hr != NULL), its top should + // match obj_top. + assert(hr == NULL || (hr->top() == obj_top), "sanity"); check_bitmaps("Humongous Region Allocation", first_hr); - assert(first_hr->used() == word_size * HeapWordSize, "invariant"); - increase_used(first_hr->used()); - _humongous_set.add(first_hr); + increase_used(word_size * HeapWordSize); + + for (uint i = first; i < last; ++i) { + _humongous_set.add(region_at(i)); + } return new_obj; } @@ -1139,15 +1113,15 @@ public: bool doHeapRegion(HeapRegion* r) { HeapRegionRemSet* hrrs = r->rem_set(); + _g1h->reset_gc_time_stamps(r); + if (r->is_continues_humongous()) { // We'll assert that the strong code root list and RSet is empty assert(hrrs->strong_code_roots_list_length() == 0, "sanity"); assert(hrrs->occupied() == 0, "RSet should be empty"); - return false; + } else { + hrrs->clear(); } - - _g1h->reset_gc_time_stamps(r); - hrrs->clear(); // You might think here that we could clear just the cards // corresponding to the used region. But no: if we leave a dirty card // in a region we might allocate into, then it would prevent that card @@ -1205,12 +1179,7 @@ public: if (hr->is_free()) { // We only generate output for non-empty regions. } else if (hr->is_starts_humongous()) { - if (hr->region_num() == 1) { - // single humongous region - _hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous); - } else { - _hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous); - } + _hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous); } else if (hr->is_continues_humongous()) { _hr_printer->post_compaction(hr, G1HRPrinter::ContinuesHumongous); } else if (hr->is_archive()) { @@ -1716,7 +1685,7 @@ HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size, AllocationConte return NULL; } -bool G1CollectedHeap::expand(size_t expand_bytes) { +bool G1CollectedHeap::expand(size_t expand_bytes, double* expand_time_ms) { size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); aligned_expand_bytes = align_size_up(aligned_expand_bytes, HeapRegion::GrainBytes); @@ -1733,10 +1702,14 @@ bool G1CollectedHeap::expand(size_t expand_bytes) { return false; } + double expand_heap_start_time_sec = os::elapsedTime(); uint regions_to_expand = (uint)(aligned_expand_bytes / HeapRegion::GrainBytes); assert(regions_to_expand > 0, "Must expand by at least one region"); uint expanded_by = _hrm.expand_by(regions_to_expand); + if (expand_time_ms != NULL) { + *expand_time_ms = (os::elapsedTime() - expand_heap_start_time_sec) * MILLIUNITS; + } if (expanded_by > 0) { size_t actual_expand_bytes = expanded_by * HeapRegion::GrainBytes; @@ -1803,16 +1776,10 @@ void G1CollectedHeap::shrink(size_t shrink_bytes) { // Public methods. -#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away -#pragma warning( disable:4355 ) // 'this' : used in base member initializer list -#endif // _MSC_VER - - G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : CollectedHeap(), _g1_policy(policy_), _dirty_card_queue_set(false), - _into_cset_dirty_card_queue_set(false), _is_alive_closure_cm(this), _is_alive_closure_stw(this), _ref_processor_cm(NULL), @@ -2077,16 +2044,6 @@ jint G1CollectedHeap::initialize() { Shared_DirtyCardQ_lock, &JavaThread::dirty_card_queue_set()); - // Initialize the card queue set used to hold cards containing - // references into the collection set. - _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code - DirtyCardQ_CBL_mon, - DirtyCardQ_FL_lock, - -1, // never trigger processing - -1, // no limit on length - Shared_DirtyCardQ_lock, - &JavaThread::dirty_card_queue_set()); - // Here we allocate the dummy HeapRegion that is required by the // G1AllocRegion class. HeapRegion* dummy_region = _hrm.get_dummy_region(); @@ -2218,17 +2175,7 @@ size_t G1CollectedHeap::capacity() const { } void G1CollectedHeap::reset_gc_time_stamps(HeapRegion* hr) { - assert(!hr->is_continues_humongous(), "pre-condition"); hr->reset_gc_time_stamp(); - if (hr->is_starts_humongous()) { - uint first_index = hr->hrm_index() + 1; - uint last_index = hr->last_hc_index(); - for (uint i = first_index; i < last_index; i += 1) { - HeapRegion* chr = region_at(i); - assert(chr->is_continues_humongous(), "sanity"); - chr->reset_gc_time_stamp(); - } - } } #ifndef PRODUCT @@ -2296,9 +2243,7 @@ class SumUsedClosure: public HeapRegionClosure { public: SumUsedClosure() : _used(0) {} bool doHeapRegion(HeapRegion* r) { - if (!r->is_continues_humongous()) { - _used += r->used(); - } + _used += r->used(); return false; } size_t result() { return _used; } @@ -2519,9 +2464,9 @@ void G1CollectedHeap::collect(GCCause::Cause cause) { bool G1CollectedHeap::is_in(const void* p) const { if (_hrm.reserved().contains(p)) { // Given that we know that p is in the reserved space, - // heap_region_containing_raw() should successfully + // heap_region_containing() should successfully // return the containing region. - HeapRegion* hr = heap_region_containing_raw(p); + HeapRegion* hr = heap_region_containing(p); return hr->is_in(p); } else { return false; @@ -3058,7 +3003,7 @@ public: r->verify(_vo, &failures); if (failures) { _failures = true; - } else { + } else if (!r->is_starts_humongous()) { VerifyObjsInRegionClosure not_dead_yet_cl(r, _vo); r->object_iterate(¬_dead_yet_cl); if (_vo != VerifyOption_G1UseNextMarking) { @@ -3609,7 +3554,7 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { // The remembered set might contain references to already freed // regions. Filter out such entries to avoid failing card table // verification. - if (!g1h->heap_region_containing(bs->addr_for(card_ptr))->is_free()) { + if (g1h->is_in_closed_subset(bs->addr_for(card_ptr))) { if (*card_ptr != CardTableModRefBS::dirty_card_val()) { *card_ptr = CardTableModRefBS::dirty_card_val(); _dcq.enqueue(card_ptr); @@ -3731,8 +3676,7 @@ void G1CollectedHeap::log_gc_footer(double pause_time_sec) { gclog_or_tty->print(" (to-space exhausted)"); } gclog_or_tty->print_cr(", %3.7f secs]", pause_time_sec); - g1_policy()->phase_times()->note_gc_end(); - g1_policy()->phase_times()->print(pause_time_sec); + g1_policy()->print_phases(pause_time_sec); g1_policy()->print_detailed_heap_transition(); } else { if (evacuation_failed()) { @@ -3823,7 +3767,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { workers()->set_active_workers(active_workers); double pause_start_sec = os::elapsedTime(); - g1_policy()->phase_times()->note_gc_start(active_workers, collector_state()->mark_in_progress()); + g1_policy()->note_gc_start(active_workers); log_gc_header(); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); @@ -3930,9 +3874,13 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { _allocator->init_gc_alloc_regions(evacuation_info); G1ParScanThreadStateSet per_thread_states(this, workers()->active_workers(), g1_policy()->young_cset_region_length()); + pre_evacuate_collection_set(); + // Actually do the work... evacuate_collection_set(evacuation_info, &per_thread_states); + post_evacuate_collection_set(evacuation_info, &per_thread_states); + const size_t* surviving_young_words = per_thread_states.surviving_young_words(); free_collection_set(g1_policy()->collection_set(), evacuation_info, surviving_young_words); @@ -3997,9 +3945,11 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { size_t bytes_before = capacity(); // No need for an ergo verbose message here, // expansion_amount() does this when it returns a value > 0. - if (!expand(expand_bytes)) { + double expand_ms; + if (!expand(expand_bytes, &expand_ms)) { // We failed to expand the heap. Cannot do anything about it. } + g1_policy()->phase_times()->record_expand_heap_time(expand_ms); } } @@ -4584,20 +4534,16 @@ class G1KlassCleaningTask : public StackObj { Klass* klass; do { klass =_klass_iterator.next_klass(); - } while (klass != NULL && !klass->oop_is_instance()); + } while (klass != NULL && !klass->is_instance_klass()); - return (InstanceKlass*)klass; + // this can be null so don't call InstanceKlass::cast + return static_cast(klass); } public: void clean_klass(InstanceKlass* ik) { - ik->clean_implementors_list(_is_alive); - ik->clean_method_data(_is_alive); - - // G1 specific cleanup work that has - // been moved here to be done in parallel. - ik->clean_dependent_nmethods(); + ik->clean_weak_instanceklass_links(_is_alive); } void work() { @@ -5164,27 +5110,29 @@ void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0); } -void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) { +void G1CollectedHeap::pre_evacuate_collection_set() { _expand_heap_after_alloc_failure = true; _evacuation_failed = false; - // Should G1EvacuationFailureALot be in effect for this GC? - NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();) - - g1_rem_set()->prepare_for_oops_into_collection_set_do(); - // Disable the hot card cache. G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache(); hot_card_cache->reset_hot_cache_claimed_index(); hot_card_cache->set_use_cache(false); - const uint n_workers = workers()->active_workers(); +} + +void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) { + g1_rem_set()->prepare_for_oops_into_collection_set_do(); + + // Should G1EvacuationFailureALot be in effect for this GC? + NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();) assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty"); double start_par_time_sec = os::elapsedTime(); double end_par_time_sec; { + const uint n_workers = workers()->active_workers(); G1RootProcessor root_processor(this, n_workers); G1ParTask g1_par_task(this, per_thread_states, _task_queues, &root_processor, n_workers); // InitialMark needs claim bits to keep track of the marked-through CLDs. @@ -5234,21 +5182,8 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info, G phase_times->record_string_dedup_fixup_time(fixup_time_ms); } - _allocator->release_gc_alloc_regions(evacuation_info); g1_rem_set()->cleanup_after_oops_into_collection_set_do(); - per_thread_states->flush(); - - record_obj_copy_mem_stats(); - - // Reset and re-enable the hot card cache. - // Note the counts for the cards in the regions in the - // collection set are reset when the collection set is freed. - hot_card_cache->reset_hot_cache(); - hot_card_cache->set_use_cache(true); - - purge_code_root_memory(); - if (evacuation_failed()) { remove_self_forwarding_pointers(); @@ -5266,6 +5201,26 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info, G // cards). We need these updates logged to update any // RSets. enqueue_discovered_references(per_thread_states); +} + +void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) { + _allocator->release_gc_alloc_regions(evacuation_info); + + per_thread_states->flush(); + + record_obj_copy_mem_stats(); + + _survivor_evac_stats.adjust_desired_plab_sz(); + _old_evac_stats.adjust_desired_plab_sz(); + + // Reset and re-enable the hot card cache. + // Note the counts for the cards in the regions in the + // collection set are reset when the collection set is freed. + G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache(); + hot_card_cache->reset_hot_cache(); + hot_card_cache->set_use_cache(true); + + purge_code_root_memory(); redirty_logged_cards(); #if defined(COMPILER2) || INCLUDE_JVMCI @@ -5303,30 +5258,16 @@ void G1CollectedHeap::free_region(HeapRegion* hr, } void G1CollectedHeap::free_humongous_region(HeapRegion* hr, - FreeRegionList* free_list, - bool par) { - assert(hr->is_starts_humongous(), "this is only for starts humongous regions"); + FreeRegionList* free_list, + bool par) { + assert(hr->is_humongous(), "this is only for humongous regions"); assert(free_list != NULL, "pre-condition"); - - size_t hr_capacity = hr->capacity(); - // We need to read this before we make the region non-humongous, - // otherwise the information will be gone. - uint last_index = hr->last_hc_index(); hr->clear_humongous(); free_region(hr, free_list, par); - - uint i = hr->hrm_index() + 1; - while (i < last_index) { - HeapRegion* curr_hr = region_at(i); - assert(curr_hr->is_continues_humongous(), "invariant"); - curr_hr->clear_humongous(); - free_region(curr_hr, free_list, par); - i += 1; - } } void G1CollectedHeap::remove_from_old_sets(const HeapRegionSetCount& old_regions_removed, - const HeapRegionSetCount& humongous_regions_removed) { + const HeapRegionSetCount& humongous_regions_removed) { if (old_regions_removed.length() > 0 || humongous_regions_removed.length() > 0) { MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag); _old_set.bulk_remove(old_regions_removed); @@ -5486,8 +5427,6 @@ public: bool failures() { return _failures; } virtual bool doHeapRegion(HeapRegion* hr) { - if (hr->is_continues_humongous()) return false; - bool result = _g1h->verify_bitmaps(_caller, hr); if (!result) { _failures = true; @@ -5761,11 +5700,10 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure { !r->rem_set()->is_empty()) { if (G1TraceEagerReclaimHumongousObjects) { - gclog_or_tty->print_cr("Live humongous region %u size " SIZE_FORMAT " start " PTR_FORMAT " length %u with remset " SIZE_FORMAT " code roots " SIZE_FORMAT " is marked %d reclaim candidate %d type array %d", + gclog_or_tty->print_cr("Live humongous region %u object size " SIZE_FORMAT " start " PTR_FORMAT " with remset " SIZE_FORMAT " code roots " SIZE_FORMAT " is marked %d reclaim candidate %d type array %d", region_idx, (size_t)obj->size() * HeapWordSize, p2i(r->bottom()), - r->region_num(), r->rem_set()->occupied(), r->rem_set()->strong_code_roots_list_length(), next_bitmap->isMarked(r->bottom()), @@ -5782,11 +5720,10 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure { PTR_FORMAT " is not.", p2i(r->bottom())); if (G1TraceEagerReclaimHumongousObjects) { - gclog_or_tty->print_cr("Dead humongous region %u size " SIZE_FORMAT " start " PTR_FORMAT " length %u with remset " SIZE_FORMAT " code roots " SIZE_FORMAT " is marked %d reclaim candidate %d type array %d", + gclog_or_tty->print_cr("Dead humongous region %u object size " SIZE_FORMAT " start " PTR_FORMAT " with remset " SIZE_FORMAT " code roots " SIZE_FORMAT " is marked %d reclaim candidate %d type array %d", region_idx, (size_t)obj->size() * HeapWordSize, p2i(r->bottom()), - r->region_num(), r->rem_set()->occupied(), r->rem_set()->strong_code_roots_list_length(), next_bitmap->isMarked(r->bottom()), @@ -5798,10 +5735,14 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure { if (next_bitmap->isMarked(r->bottom())) { next_bitmap->clear(r->bottom()); } - _freed_bytes += r->used(); - r->set_containing_set(NULL); - _humongous_regions_removed.increment(1u, r->capacity()); - g1h->free_humongous_region(r, _free_region_list, false); + do { + HeapRegion* next = g1h->next_region_in_humongous(r); + _freed_bytes += r->used(); + r->set_containing_set(NULL); + _humongous_regions_removed.increment(1u, r->capacity()); + g1h->free_humongous_region(r, _free_region_list, false); + r = next; + } while (r != NULL); return false; } @@ -6036,10 +5977,6 @@ public: } bool doHeapRegion(HeapRegion* r) { - if (r->is_continues_humongous()) { - return false; - } - if (r->is_empty()) { // Add free regions to the free list r->set_free(); @@ -6227,14 +6164,10 @@ public: _old_count(), _humongous_count(), _free_count(){ } bool doHeapRegion(HeapRegion* hr) { - if (hr->is_continues_humongous()) { - return false; - } - if (hr->is_young()) { // TODO - } else if (hr->is_starts_humongous()) { - assert(hr->containing_set() == _humongous_set, "Heap region %u is starts humongous but not in humongous set.", hr->hrm_index()); + } else if (hr->is_humongous()) { + assert(hr->containing_set() == _humongous_set, "Heap region %u is humongous but not in humongous set.", hr->hrm_index()); _humongous_count.increment(1u, hr->capacity()); } else if (hr->is_empty()) { assert(_hrm->is_free(hr), "Heap region %u is empty but not on the free list.", hr->hrm_index()); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index dc4c5ef1a80..e34e1684493 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -538,7 +538,7 @@ public: // Returns true if the heap was expanded by the requested amount; // false otherwise. // (Rounds up to a HeapRegion boundary.) - bool expand(size_t expand_bytes); + bool expand(size_t expand_bytes, double* expand_time_ms = NULL); // Returns the PLAB statistics for a given destination. inline G1EvacStats* alloc_buffer_stats(InCSetState dest); @@ -728,7 +728,10 @@ protected: bool do_collection_pause_at_safepoint(double target_pause_time_ms); // Actually do the work of evacuating the collection set. - void evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states); + virtual void evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states); + + void pre_evacuate_collection_set(); + void post_evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss); // Print the header for the per-thread termination statistics. static void print_termination_stats_hdr(outputStream* const st); @@ -754,12 +757,6 @@ protected: // The closure used to refine a single card. RefineCardTableEntryClosure* _refine_cte_cl; - // A DirtyCardQueueSet that is used to hold cards that contain - // references into the current collection set. This is used to - // update the remembered sets of the regions in the collection - // set in the event of an evacuation failure. - DirtyCardQueueSet _into_cset_dirty_card_queue_set; - // After a collection pause, make the regions in the CS into free // regions. void free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info, const size_t* surviving_young_words); @@ -949,13 +946,6 @@ public: // A set of cards where updates happened during the GC DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; } - // A DirtyCardQueueSet that is used to hold cards that contain - // references into the current collection set. This is used to - // update the remembered sets of the regions in the collection - // set in the event of an evacuation failure. - DirtyCardQueueSet& into_cset_dirty_card_queue_set() - { return _into_cset_dirty_card_queue_set; } - // Create a G1CollectedHeap with the specified policy. // Must call the initialize method afterwards. // May not return if something goes wrong. @@ -1175,7 +1165,6 @@ public: void prepend_to_freelist(FreeRegionList* list); void decrement_summary_bytes(size_t bytes); - // Returns "TRUE" iff "p" points into the committed areas of the heap. virtual bool is_in(const void* p) const; #ifdef ASSERT // Returns whether p is in one of the available areas of the heap. Slow but @@ -1240,6 +1229,10 @@ public: // Return the region with the given index. It assumes the index is valid. inline HeapRegion* region_at(uint index) const; + // Return the next region (by index) that is part of the same + // humongous object that hr is part of. + inline HeapRegion* next_region_in_humongous(HeapRegion* hr) const; + // Calculate the region index of the given address. Given address must be // within the heap. inline uint addr_to_region(HeapWord* addr) const; @@ -1277,11 +1270,6 @@ public: // Returns the HeapRegion that contains addr. addr must not be NULL. template - inline HeapRegion* heap_region_containing_raw(const T addr) const; - - // Returns the HeapRegion that contains addr. addr must not be NULL. - // If addr is within a humongous continues region, it returns its humongous start region. - template inline HeapRegion* heap_region_containing(const T addr) const; // A CollectedHeap is divided into a dense sequence of "blocks"; that is, diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp index 9478dcac231..06143806d59 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp @@ -65,6 +65,10 @@ inline AllocationContextStats& G1CollectedHeap::allocation_context_stats() { // Return the region with the given index. It assumes the index is valid. inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrm.at(index); } +inline HeapRegion* G1CollectedHeap::next_region_in_humongous(HeapRegion* hr) const { + return _hrm.next_region_in_humongous(hr); +} + inline uint G1CollectedHeap::addr_to_region(HeapWord* addr) const { assert(is_in_reserved(addr), "Cannot calculate region index for address " PTR_FORMAT " that is outside of the heap [" PTR_FORMAT ", " PTR_FORMAT ")", @@ -77,7 +81,7 @@ inline HeapWord* G1CollectedHeap::bottom_addr_for_region(uint index) const { } template -inline HeapRegion* G1CollectedHeap::heap_region_containing_raw(const T addr) const { +inline HeapRegion* G1CollectedHeap::heap_region_containing(const T addr) const { assert(addr != NULL, "invariant"); assert(is_in_g1_reserved((const void*) addr), "Address " PTR_FORMAT " is outside of the heap ranging from [" PTR_FORMAT " to " PTR_FORMAT ")", @@ -85,15 +89,6 @@ inline HeapRegion* G1CollectedHeap::heap_region_containing_raw(const T addr) con return _hrm.addr_to_region((HeapWord*) addr); } -template -inline HeapRegion* G1CollectedHeap::heap_region_containing(const T addr) const { - HeapRegion* hr = heap_region_containing_raw(addr); - if (hr->is_continues_humongous()) { - return hr->humongous_start_region(); - } - return hr; -} - inline void G1CollectedHeap::reset_gc_time_stamp() { _gc_time_stamp = 0; OrderAccess::fence(); @@ -124,9 +119,9 @@ G1CollectedHeap::dirty_young_block(HeapWord* start, size_t word_size) { assert_heap_not_locked(); // Assign the containing region to containing_hr so that we don't - // have to keep calling heap_region_containing_raw() in the + // have to keep calling heap_region_containing() in the // asserts below. - DEBUG_ONLY(HeapRegion* containing_hr = heap_region_containing_raw(start);) + DEBUG_ONLY(HeapRegion* containing_hr = heap_region_containing(start);) assert(word_size > 0, "pre-condition"); assert(containing_hr->is_in(start), "it should contain start"); assert(containing_hr->is_young(), "it should be young"); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index 41cdd6c5a33..ee558818f83 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -431,12 +431,16 @@ void G1CollectorPolicy::init() { } _free_regions_at_end_of_collection = _g1->num_free_regions(); - update_young_list_target_length(); + update_young_list_max_and_target_length(); // We may immediately start allocating regions and placing them on the // collection set list. Initialize the per-collection set info start_incremental_cset_building(); } +void G1CollectorPolicy::note_gc_start(uint num_active_workers) { + phase_times()->note_gc_start(num_active_workers); +} + // Create the jstat counters for the policy. void G1CollectorPolicy::initialize_gc_policy_counters() { _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 3); @@ -507,13 +511,24 @@ uint G1CollectorPolicy::calculate_young_list_desired_max_length() const { return _young_gen_sizer->max_desired_young_length(); } -void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { - if (rs_lengths == (size_t) -1) { - // if it's set to the default value (-1), we should predict it; - // otherwise, use the given value. - rs_lengths = (size_t) get_new_prediction(_rs_lengths_seq); - } +void G1CollectorPolicy::update_young_list_max_and_target_length() { + update_young_list_max_and_target_length(get_new_prediction(_rs_lengths_seq)); +} +void G1CollectorPolicy::update_young_list_max_and_target_length(size_t rs_lengths) { + update_young_list_target_length(rs_lengths); + update_max_gc_locker_expansion(); +} + +void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { + _young_list_target_length = bounded_young_list_target_length(rs_lengths); +} + +void G1CollectorPolicy::update_young_list_target_length() { + update_young_list_target_length(get_new_prediction(_rs_lengths_seq)); +} + +uint G1CollectorPolicy::bounded_young_list_target_length(size_t rs_lengths) const { // Calculate the absolute and desired min bounds. // This is how many young regions we already have (currently: the survivors). @@ -544,7 +559,6 @@ void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { base_min_length, desired_min_length, desired_max_length); - _rs_lengths_prediction = rs_lengths; } else { // Don't calculate anything and let the code below bound it to // the desired_min_length, i.e., do the next GC as soon as @@ -569,9 +583,8 @@ void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { assert(young_list_target_length > recorded_survivor_regions(), "we should be able to allocate at least one eden region"); assert(young_list_target_length >= absolute_min_length, "post-condition"); - _young_list_target_length = young_list_target_length; - update_max_gc_locker_expansion(); + return young_list_target_length; } uint @@ -695,11 +708,21 @@ void G1CollectorPolicy::revise_young_list_target_length_if_necessary() { if (rs_lengths > _rs_lengths_prediction) { // add 10% to avoid having to recalculate often size_t rs_lengths_prediction = rs_lengths * 1100 / 1000; - update_young_list_target_length(rs_lengths_prediction); + update_rs_lengths_prediction(rs_lengths_prediction); + + update_young_list_max_and_target_length(rs_lengths_prediction); } } +void G1CollectorPolicy::update_rs_lengths_prediction() { + update_rs_lengths_prediction(get_new_prediction(_rs_lengths_seq)); +} +void G1CollectorPolicy::update_rs_lengths_prediction(size_t prediction) { + if (collector_state()->gcs_are_young() && adaptive_young_list_length()) { + _rs_lengths_prediction = prediction; + } +} HeapWord* G1CollectorPolicy::mem_allocate_work(size_t size, bool is_tlab, @@ -788,7 +811,7 @@ void G1CollectorPolicy::record_full_collection_end() { // transitions and make sure we start with young GCs after the Full GC. collector_state()->set_gcs_are_young(true); collector_state()->set_last_young_gc(false); - collector_state()->set_initiate_conc_mark_if_possible(false); + collector_state()->set_initiate_conc_mark_if_possible(need_to_start_conc_mark("end of Full GC", 0)); collector_state()->set_during_initial_mark_pause(false); collector_state()->set_in_marking_window(false); collector_state()->set_in_marking_window_im(false); @@ -801,7 +824,8 @@ void G1CollectorPolicy::record_full_collection_end() { _free_regions_at_end_of_collection = _g1->num_free_regions(); // Reset survivors SurvRateGroup. _survivor_surv_rate_group->reset(); - update_young_list_target_length(); + update_young_list_max_and_target_length(); + update_rs_lengths_prediction(); _collectionSetChooser->clear(); } @@ -868,7 +892,9 @@ void G1CollectorPolicy::record_concurrent_mark_cleanup_start() { } void G1CollectorPolicy::record_concurrent_mark_cleanup_completed() { - collector_state()->set_last_young_gc(true); + bool should_continue_with_reclaim = next_gc_should_be_mixed("request last young-only gc", + "skip last young-only gc"); + collector_state()->set_last_young_gc(should_continue_with_reclaim); collector_state()->set_in_marking_window(false); } @@ -879,8 +905,39 @@ void G1CollectorPolicy::record_concurrent_pause() { } } +double G1CollectorPolicy::average_time_ms(G1GCPhaseTimes::GCParPhases phase) const { + return phase_times()->average_time_ms(phase); +} + +double G1CollectorPolicy::young_other_time_ms() const { + return phase_times()->young_cset_choice_time_ms() + + phase_times()->young_free_cset_time_ms(); +} + +double G1CollectorPolicy::non_young_other_time_ms() const { + return phase_times()->non_young_cset_choice_time_ms() + + phase_times()->non_young_free_cset_time_ms(); + +} + +double G1CollectorPolicy::other_time_ms(double pause_time_ms) const { + return pause_time_ms - + average_time_ms(G1GCPhaseTimes::UpdateRS) - + average_time_ms(G1GCPhaseTimes::ScanRS) - + average_time_ms(G1GCPhaseTimes::ObjCopy) - + average_time_ms(G1GCPhaseTimes::Termination); +} + +double G1CollectorPolicy::constant_other_time_ms(double pause_time_ms) const { + return other_time_ms(pause_time_ms) - young_other_time_ms() - non_young_other_time_ms(); +} + +bool G1CollectorPolicy::about_to_start_mixed_phase() const { + return _g1->concurrent_mark()->cmThread()->during_cycle() || collector_state()->last_young_gc(); +} + bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc_word_size) { - if (_g1->concurrent_mark()->cmThread()->during_cycle()) { + if (about_to_start_mixed_phase()) { return false; } @@ -948,11 +1005,8 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t last_pause_included_initial_mark = collector_state()->during_initial_mark_pause(); if (last_pause_included_initial_mark) { record_concurrent_mark_init_end(0.0); - } else if (need_to_start_conc_mark("end of GC")) { - // Note: this might have already been set, if during the last - // pause we decided to start a cycle but at the beginning of - // this pause we decided to postpone it. That's OK. - collector_state()->set_initiate_conc_mark_if_possible(true); + } else { + maybe_start_marking(); } _mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0, end_time_sec); @@ -986,19 +1040,6 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t _recent_avg_pause_time_ratio = _recent_gc_times_ms->sum()/interval_ms; if (recent_avg_pause_time_ratio() < 0.0 || (recent_avg_pause_time_ratio() - 1.0 > 0.0)) { -#ifndef PRODUCT - // Dump info to allow post-facto debugging - gclog_or_tty->print_cr("recent_avg_pause_time_ratio() out of bounds"); - gclog_or_tty->print_cr("-------------------------------------------"); - gclog_or_tty->print_cr("Recent GC Times (ms):"); - _recent_gc_times_ms->dump(); - gclog_or_tty->print_cr("(End Time=%3.3f) Recent GC End Times (s):", end_time_sec); - _recent_prev_end_times_for_all_gcs_sec->dump(); - gclog_or_tty->print_cr("GC = %3.3f, Interval = %3.3f, Ratio = %3.3f", - _recent_gc_times_ms->sum(), interval_ms, recent_avg_pause_time_ratio()); - // In debug mode, terminate the JVM if the user wants to debug at this point. - assert(!G1FailOnFPError, "Debugging data for CR 6898948 has been dumped above"); -#endif // !PRODUCT // Clip ratio between 0.0 and 1.0, and continue. This will be fixed in // CR 6902692 by redoing the manner in which the ratio is incrementally computed. if (_recent_avg_pause_time_ratio < 0.0) { @@ -1020,17 +1061,13 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t if (collector_state()->last_young_gc()) { // This is supposed to to be the "last young GC" before we start // doing mixed GCs. Here we decide whether to start mixed GCs or not. + assert(!last_pause_included_initial_mark, "The last young GC is not allowed to be an initial mark GC"); - if (!last_pause_included_initial_mark) { - if (next_gc_should_be_mixed("start mixed GCs", - "do not start mixed GCs")) { - collector_state()->set_gcs_are_young(false); - } - } else { - ergo_verbose0(ErgoMixedGCs, - "do not start mixed GCs", - ergo_format_reason("concurrent cycle is about to start")); + if (next_gc_should_be_mixed("start mixed GCs", + "do not start mixed GCs")) { + collector_state()->set_gcs_are_young(false); } + collector_state()->set_last_young_gc(false); } @@ -1041,6 +1078,8 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t if (!next_gc_should_be_mixed("continue mixed GCs", "do not continue mixed GCs")) { collector_state()->set_gcs_are_young(true); + + maybe_start_marking(); } } @@ -1049,16 +1088,16 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t if (update_stats) { double cost_per_card_ms = 0.0; - double cost_scan_hcc = phase_times()->average_time_ms(G1GCPhaseTimes::ScanHCC); + double cost_scan_hcc = average_time_ms(G1GCPhaseTimes::ScanHCC); if (_pending_cards > 0) { - cost_per_card_ms = (phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) - cost_scan_hcc) / (double) _pending_cards; + cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS) - cost_scan_hcc) / (double) _pending_cards; _cost_per_card_ms_seq->add(cost_per_card_ms); } _cost_scan_hcc_seq->add(cost_scan_hcc); double cost_per_entry_ms = 0.0; if (cards_scanned > 10) { - cost_per_entry_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned; + cost_per_entry_ms = average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned; if (collector_state()->last_gc_was_young()) { _cost_per_entry_ms_seq->add(cost_per_entry_ms); } else { @@ -1100,7 +1139,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t double cost_per_byte_ms = 0.0; if (copied_bytes > 0) { - cost_per_byte_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes; + cost_per_byte_ms = average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes; if (collector_state()->in_marking_window()) { _cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms); } else { @@ -1108,37 +1147,17 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t } } - double all_other_time_ms = pause_time_ms - - (phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) + phase_times()->average_time_ms(G1GCPhaseTimes::ScanRS) + - phase_times()->average_time_ms(G1GCPhaseTimes::ObjCopy) + phase_times()->average_time_ms(G1GCPhaseTimes::Termination)); - - double young_other_time_ms = 0.0; if (young_cset_region_length() > 0) { - young_other_time_ms = - phase_times()->young_cset_choice_time_ms() + - phase_times()->young_free_cset_time_ms(); - _young_other_cost_per_region_ms_seq->add(young_other_time_ms / - (double) young_cset_region_length()); + _young_other_cost_per_region_ms_seq->add(young_other_time_ms() / + young_cset_region_length()); } - double non_young_other_time_ms = 0.0; + if (old_cset_region_length() > 0) { - non_young_other_time_ms = - phase_times()->non_young_cset_choice_time_ms() + - phase_times()->non_young_free_cset_time_ms(); - - _non_young_other_cost_per_region_ms_seq->add(non_young_other_time_ms / - (double) old_cset_region_length()); + _non_young_other_cost_per_region_ms_seq->add(non_young_other_time_ms() / + old_cset_region_length()); } - double constant_other_time_ms = all_other_time_ms - - (young_other_time_ms + non_young_other_time_ms); - _constant_other_time_ms_seq->add(constant_other_time_ms); - - double survival_ratio = 0.0; - if (_collection_set_bytes_used_before > 0) { - survival_ratio = (double) _bytes_copied_during_gc / - (double) _collection_set_bytes_used_before; - } + _constant_other_time_ms_seq->add(constant_other_time_ms(pause_time_ms)); _pending_cards_seq->add((double) _pending_cards); _rs_lengths_seq->add((double) _max_rs_lengths); @@ -1147,12 +1166,13 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t collector_state()->set_in_marking_window(new_in_marking_window); collector_state()->set_in_marking_window_im(new_in_marking_window_im); _free_regions_at_end_of_collection = _g1->num_free_regions(); - update_young_list_target_length(); + update_young_list_max_and_target_length(); + update_rs_lengths_prediction(); // Note that _mmu_tracker->max_gc_time() returns the time in seconds. double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; - double scan_hcc_time_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ScanHCC); + double scan_hcc_time_ms = average_time_ms(G1GCPhaseTimes::ScanHCC); if (update_rs_time_goal_ms < scan_hcc_time_ms) { ergo_verbose2(ErgoTiming, @@ -1167,7 +1187,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t } else { update_rs_time_goal_ms -= scan_hcc_time_ms; } - adjust_concurrent_refinement(phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms, + adjust_concurrent_refinement(average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms, phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS), update_rs_time_goal_ms); @@ -1246,6 +1266,10 @@ void G1CollectorPolicy::print_detailed_heap_transition(bool full) const { gclog_or_tty->cr(); } +void G1CollectorPolicy::print_phases(double pause_time_sec) { + phase_times()->print(pause_time_sec); +} + void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, double update_rs_processed_buffers, double goal_ms) { @@ -1563,8 +1587,10 @@ void G1CollectorPolicy::update_survivors_policy() { HeapRegion::GrainWords * _max_survivor_regions, counters()); } -bool G1CollectorPolicy::force_initial_mark_if_outside_cycle( - GCCause::Cause gc_cause) { +bool G1CollectorPolicy::force_initial_mark_if_outside_cycle(GCCause::Cause gc_cause) { + // We actually check whether we are marking here and not if we are in a + // reclamation phase. This means that we will schedule a concurrent mark + // even while we are still in the process of reclaiming memory. bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle(); if (!during_cycle) { ergo_verbose1(ErgoConcCycles, @@ -1584,8 +1610,7 @@ bool G1CollectorPolicy::force_initial_mark_if_outside_cycle( } } -void -G1CollectorPolicy::decide_on_conc_mark_initiation() { +void G1CollectorPolicy::decide_on_conc_mark_initiation() { // We are about to decide on whether this pause will be an // initial-mark pause. @@ -1600,21 +1625,11 @@ G1CollectorPolicy::decide_on_conc_mark_initiation() { // gone over the initiating threshold and we should start a // concurrent marking cycle. So we might initiate one. - bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle(); - if (!during_cycle) { - // The concurrent marking thread is not "during a cycle", i.e., - // it has completed the last one. So we can go ahead and - // initiate a new cycle. + if (!about_to_start_mixed_phase() && collector_state()->gcs_are_young()) { + // Initiate a new initial mark only if there is no marking or reclamation going + // on. collector_state()->set_during_initial_mark_pause(true); - // We do not allow mixed GCs during marking. - if (!collector_state()->gcs_are_young()) { - collector_state()->set_gcs_are_young(true); - ergo_verbose0(ErgoMixedGCs, - "end mixed GCs", - ergo_format_reason("concurrent cycle is about to start")); - } - // And we can now clear initiate_conc_mark_if_possible() as // we've already acted on it. collector_state()->set_initiate_conc_mark_if_possible(false); @@ -1918,6 +1933,15 @@ double G1CollectorPolicy::reclaimable_bytes_perc(size_t reclaimable_bytes) const return (double) reclaimable_bytes * 100.0 / (double) capacity_bytes; } +void G1CollectorPolicy::maybe_start_marking() { + if (need_to_start_conc_mark("end of GC")) { + // Note: this might have already been set, if during the last + // pause we decided to start a cycle but at the beginning of + // this pause we decided to postpone it. That's OK. + collector_state()->set_initiate_conc_mark_if_possible(true); + } +} + bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str, const char* false_action_str) const { CollectionSetChooser* cset_chooser = _collectionSetChooser; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp index 8904170bcaf..8ed9a72502f 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp @@ -27,6 +27,7 @@ #include "gc/g1/collectionSetChooser.hpp" #include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1InCSetState.hpp" #include "gc/g1/g1MMUTracker.hpp" #include "gc/g1/g1Predictions.hpp" @@ -39,7 +40,6 @@ class HeapRegion; class CollectionSetChooser; -class G1GCPhaseTimes; // TraceYoungGenTime collects data on _both_ young and mixed evacuation pauses // (the latter may contain non-young regions - i.e. regions that are @@ -378,6 +378,14 @@ public: double accum_yg_surv_rate_pred(int age) const; +protected: + virtual double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const; + virtual double other_time_ms(double pause_time_ms) const; + + double young_other_time_ms() const; + double non_young_other_time_ms() const; + double constant_other_time_ms(double pause_time_ms) const; + private: // Statistics kept per GC stoppage, pause or full. TruncatedSeq* _recent_prev_end_times_for_all_gcs_sec; @@ -465,12 +473,16 @@ private: double _mark_remark_start_sec; double _mark_cleanup_start_sec; + void update_young_list_max_and_target_length(); + void update_young_list_max_and_target_length(size_t rs_lengths); + // Update the young list target length either by setting it to the // desired fixed value or by calculating it using G1's pause // prediction model. If no rs_lengths parameter is passed, predict // the RS lengths using the prediction model, otherwise use the // given rs_lengths as the prediction. - void update_young_list_target_length(size_t rs_lengths = (size_t) -1); + void update_young_list_target_length(); + void update_young_list_target_length(size_t rs_lengths); // Calculate and return the minimum desired young list target // length. This is the minimum desired young list length according @@ -493,6 +505,11 @@ private: uint desired_min_length, uint desired_max_length) const; + uint bounded_young_list_target_length(size_t rs_lengths) const; + + void update_rs_lengths_prediction(); + void update_rs_lengths_prediction(size_t prediction); + // Calculate and return chunk size (in number of regions) for parallel // concurrent mark cleanup. uint calculate_parallel_work_chunk_size(uint n_workers, uint n_regions) const; @@ -517,6 +534,8 @@ private: // as a percentage of the current heap capacity. double reclaimable_bytes_perc(size_t reclaimable_bytes) const; + // Sets up marking if proper conditions are met. + void maybe_start_marking(); public: G1CollectorPolicy(); @@ -537,6 +556,8 @@ public: void init(); + virtual void note_gc_start(uint num_active_workers); + // Create jstat counters for the policy. virtual void initialize_gc_policy_counters(); @@ -551,6 +572,8 @@ public: bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0); + bool about_to_start_mixed_phase() const; + // Record the start and end of an evacuation pause. void record_collection_pause_start(double start_time_sec); void record_collection_pause_end(double pause_time_ms, size_t cards_scanned); @@ -581,6 +604,8 @@ public: void print_heap_transition() const; void print_detailed_heap_transition(bool full = false) const; + virtual void print_phases(double pause_time_sec); + void record_stop_world_start(); void record_concurrent_pause(); diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp index 349982f4f9d..de0e5eda296 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp @@ -104,9 +104,12 @@ void G1EvacStats::adjust_desired_plab_sz() { // Latch the result _desired_net_plab_sz = plab_sz; if (PrintPLAB) { - gclog_or_tty->print_cr(" (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ") ", cur_plab_sz, plab_sz); + gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ") ", cur_plab_sz, plab_sz); } } + if (PrintPLAB) { + gclog_or_tty->cr(); + } // Clear accumulators for next round. reset(); } diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index c9d6ae92c55..0e928b2089d 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -28,6 +28,7 @@ #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1Log.hpp" #include "gc/g1/g1StringDedup.hpp" +#include "gc/g1/workerDataArray.inline.hpp" #include "memory/allocation.hpp" #include "runtime/os.hpp" @@ -86,165 +87,6 @@ public: } }; -template -class WorkerDataArray : public CHeapObj { - friend class G1GCParPhasePrinter; - T* _data; - uint _length; - const char* _title; - bool _print_sum; - int _log_level; - uint _indent_level; - bool _enabled; - - WorkerDataArray* _thread_work_items; - - NOT_PRODUCT(T uninitialized();) - - // We are caching the sum and average to only have to calculate them once. - // This is not done in an MT-safe way. It is intended to allow single - // threaded code to call sum() and average() multiple times in any order - // without having to worry about the cost. - bool _has_new_data; - T _sum; - T _min; - T _max; - double _average; - - public: - WorkerDataArray(uint length, const char* title, bool print_sum, int log_level, uint indent_level) : - _title(title), _length(0), _print_sum(print_sum), _log_level(log_level), _indent_level(indent_level), - _has_new_data(true), _thread_work_items(NULL), _enabled(true) { - assert(length > 0, "Must have some workers to store data for"); - _length = length; - _data = NEW_C_HEAP_ARRAY(T, _length, mtGC); - } - - ~WorkerDataArray() { - FREE_C_HEAP_ARRAY(T, _data); - } - - void link_thread_work_items(WorkerDataArray* thread_work_items) { - _thread_work_items = thread_work_items; - } - - WorkerDataArray* thread_work_items() { return _thread_work_items; } - - void set(uint worker_i, T value) { - assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length); - assert(_data[worker_i] == WorkerDataArray::uninitialized(), "Overwriting data for worker %d in %s", worker_i, _title); - _data[worker_i] = value; - _has_new_data = true; - } - - void set_thread_work_item(uint worker_i, size_t value) { - assert(_thread_work_items != NULL, "No sub count"); - _thread_work_items->set(worker_i, value); - } - - T get(uint worker_i) { - assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length); - assert(_data[worker_i] != WorkerDataArray::uninitialized(), "No data added for worker %d", worker_i); - return _data[worker_i]; - } - - void add(uint worker_i, T value) { - assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length); - assert(_data[worker_i] != WorkerDataArray::uninitialized(), "No data to add to for worker %d", worker_i); - _data[worker_i] += value; - _has_new_data = true; - } - - double average(uint active_threads){ - calculate_totals(active_threads); - return _average; - } - - T sum(uint active_threads) { - calculate_totals(active_threads); - return _sum; - } - - T minimum(uint active_threads) { - calculate_totals(active_threads); - return _min; - } - - T maximum(uint active_threads) { - calculate_totals(active_threads); - return _max; - } - - void reset() PRODUCT_RETURN; - void verify(uint active_threads) PRODUCT_RETURN; - - void set_enabled(bool enabled) { _enabled = enabled; } - - int log_level() { return _log_level; } - - private: - - void calculate_totals(uint active_threads){ - if (!_has_new_data) { - return; - } - - _sum = (T)0; - _min = _data[0]; - _max = _min; - assert(active_threads <= _length, "Wrong number of active threads"); - for (uint i = 0; i < active_threads; ++i) { - T val = _data[i]; - _sum += val; - _min = MIN2(_min, val); - _max = MAX2(_max, val); - } - _average = (double)_sum / (double)active_threads; - _has_new_data = false; - } -}; - - -#ifndef PRODUCT - -template <> -size_t WorkerDataArray::uninitialized() { - return (size_t)-1; -} - -template <> -double WorkerDataArray::uninitialized() { - return -1.0; -} - -template -void WorkerDataArray::reset() { - for (uint i = 0; i < _length; i++) { - _data[i] = WorkerDataArray::uninitialized(); - } - if (_thread_work_items != NULL) { - _thread_work_items->reset(); - } -} - -template -void WorkerDataArray::verify(uint active_threads) { - if (!_enabled) { - return; - } - - assert(active_threads <= _length, "Wrong number of active threads"); - for (uint i = 0; i < active_threads; i++) { - assert(_data[i] != WorkerDataArray::uninitialized(), - "Invalid data for worker %u in '%s'", i, _title); - } - if (_thread_work_items != NULL) { - _thread_work_items->verify(active_threads); - } -} - -#endif - G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _max_gc_threads(max_gc_threads) { @@ -294,10 +136,11 @@ G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards); } -void G1GCPhaseTimes::note_gc_start(uint active_gc_threads, bool mark_in_progress) { +void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { assert(active_gc_threads > 0, "The number of threads must be > 0"); assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max number of threads"); _active_gc_threads = active_gc_threads; + _cur_expand_heap_time_ms = 0.0; for (int i = 0; i < GCParPhasesSentinel; i++) { _gc_par_phases[i]->reset(); @@ -363,6 +206,9 @@ double G1GCPhaseTimes::accounted_time_ms() { // current value of "other time" misc_time_ms += _cur_clear_ct_time_ms; + // Remove expand heap time from "other time" + misc_time_ms += _cur_expand_heap_time_ms; + return misc_time_ms; } @@ -516,6 +362,8 @@ class G1GCParPhasePrinter : public StackObj { }; void G1GCPhaseTimes::print(double pause_time_sec) { + note_gc_end(); + G1GCParPhasePrinter par_phase_printer(this); if (_root_region_scan_wait_time_ms > 0.0) { @@ -536,6 +384,8 @@ void G1GCPhaseTimes::print(double pause_time_sec) { } } print_stats(1, "Clear CT", _cur_clear_ct_time_ms); + print_stats(1, "Expand Heap After Collection", _cur_expand_heap_time_ms); + double misc_time_ms = pause_time_sec * MILLIUNITS - accounted_time_ms(); print_stats(1, "Other", misc_time_ms); if (_cur_verify_before_time_ms > 0.0) { diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp index 87752426d04..f8685548912 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp @@ -92,6 +92,7 @@ class G1GCPhaseTimes : public CHeapObj { double _cur_string_dedup_fixup_time_ms; double _cur_clear_ct_time_ms; + double _cur_expand_heap_time_ms; double _cur_ref_proc_time_ms; double _cur_ref_enq_time_ms; @@ -120,10 +121,11 @@ class G1GCPhaseTimes : public CHeapObj { void print_stats(int level, const char* str, size_t value); void print_stats(int level, const char* str, double value, uint workers); + void note_gc_end(); + public: G1GCPhaseTimes(uint max_gc_threads); - void note_gc_start(uint active_gc_threads, bool mark_in_progress); - void note_gc_end(); + void note_gc_start(uint active_gc_threads); void print(double pause_time_sec); // record the time a phase took in seconds @@ -155,6 +157,10 @@ class G1GCPhaseTimes : public CHeapObj { _cur_clear_ct_time_ms = ms; } + void record_expand_heap_time(double ms) { + _cur_expand_heap_time_ms = ms; + } + void record_par_time(double ms) { _cur_collection_par_time_ms = ms; } @@ -252,6 +258,10 @@ class G1GCPhaseTimes : public CHeapObj { return _cur_clear_ct_time_ms; } + double cur_expand_heap_time_ms() { + return _cur_expand_heap_time_ms; + } + double root_region_scan_wait_time_ms() { return _root_region_scan_wait_time_ms; } diff --git a/hotspot/src/share/vm/gc/g1/g1HRPrinter.cpp b/hotspot/src/share/vm/gc/g1/g1HRPrinter.cpp index 3ddd79a699e..3e71725274d 100644 --- a/hotspot/src/share/vm/gc/g1/g1HRPrinter.cpp +++ b/hotspot/src/share/vm/gc/g1/g1HRPrinter.cpp @@ -51,7 +51,6 @@ const char* G1HRPrinter::region_type_name(RegionType type) { case Eden: return "Eden"; case Survivor: return "Survivor"; case Old: return "Old"; - case SingleHumongous: return "SingleH"; case StartsHumongous: return "StartsH"; case ContinuesHumongous: return "ContinuesH"; case Archive: return "Archive"; diff --git a/hotspot/src/share/vm/gc/g1/g1HRPrinter.hpp b/hotspot/src/share/vm/gc/g1/g1HRPrinter.hpp index 273e390ad53..6bd1dc49f48 100644 --- a/hotspot/src/share/vm/gc/g1/g1HRPrinter.hpp +++ b/hotspot/src/share/vm/gc/g1/g1HRPrinter.hpp @@ -50,7 +50,6 @@ public: Eden, Survivor, Old, - SingleHumongous, StartsHumongous, ContinuesHumongous, Archive diff --git a/hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp b/hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp index 6edb16bf1c7..c8a09af2adc 100644 --- a/hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp +++ b/hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp @@ -29,11 +29,23 @@ #include "memory/allocation.hpp" #include "utilities/debug.hpp" -// Keeps track of the GC work and decides when it is OK to do GC work +// Two major user controls over G1 behavior are setting a pause time goal (MaxGCPauseMillis), +// over a time slice (GCPauseIntervalMillis). This defines the Minimum Mutator +// Utilisation (MMU) goal. +// +// * Definitions * +// Mutator Utilisation: +// - for a given time slice duration "ts", +// - mutator utilisation is the following fraction: +// non_gc_time / ts +// +// Minimum Mutator Utilisation (MMU): +// - the worst mutator utilisation across all time slices. +// +// G1MMUTracker keeps track of the GC work and decides when it is OK to do GC work // and for how long so that the MMU invariants are maintained. - -/***** ALL TIMES ARE IN SECS!!!!!!! *****/ - +// +// ***** ALL TIMES ARE IN SECS!!!!!!! ***** // this is the "interface" class G1MMUTracker: public CHeapObj { protected: diff --git a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp index 431a64bb52f..ca5aa98b62e 100644 --- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp +++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp @@ -279,8 +279,8 @@ public: } else { assert(hr->is_empty(), "Should have been cleared in phase 2."); } - hr->reset_during_compaction(); } + hr->reset_during_compaction(); } else if (!hr->is_pinned()) { hr->compact(); } @@ -334,9 +334,6 @@ void G1PrepareCompactClosure::free_humongous_region(HeapRegion* hr) { HeapWord* end = hr->end(); FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); - assert(hr->is_starts_humongous(), - "Only the start of a humongous region should be freed."); - hr->set_containing_set(NULL); _humongous_regions_removed.increment(1u, hr->capacity()); @@ -373,15 +370,12 @@ void G1PrepareCompactClosure::update_sets() { bool G1PrepareCompactClosure::doHeapRegion(HeapRegion* hr) { if (hr->is_humongous()) { - if (hr->is_starts_humongous()) { - oop obj = oop(hr->bottom()); - if (obj->is_gc_marked()) { - obj->forward_to(obj); - } else { - free_humongous_region(hr); - } - } else { - assert(hr->is_continues_humongous(), "Invalid humongous."); + oop obj = oop(hr->humongous_start_region()->bottom()); + if (hr->is_starts_humongous() && obj->is_gc_marked()) { + obj->forward_to(obj); + } + if (!obj->is_gc_marked()) { + free_humongous_region(hr); } } else if (!hr->is_pinned()) { prepare_for_compaction(hr, hr->end()); diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp index c6cef194d71..176191f7445 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp @@ -117,11 +117,6 @@ inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) { template inline void G1CMOopClosure::do_oop_nv(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] we're looking at location " - "*" PTR_FORMAT " = " PTR_FORMAT, - _task->worker_id(), p2i(p), p2i((void*) obj)); - } _task->deal_with_reference(obj); } @@ -227,7 +222,7 @@ inline void G1UpdateRSOrPushRefOopClosure::do_oop_nv(T* p) { template void G1ParCopyHelper::do_klass_barrier(T* p, oop new_obj) { - if (_g1->heap_region_containing_raw(new_obj)->is_young()) { + if (_g1->heap_region_containing(new_obj)->is_young()) { _scanned_klass->record_modified_oops(); } } diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp index 8ddc22852dc..f22c6e2195c 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp @@ -216,7 +216,7 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, oop const old, markOop const old_mark) { const size_t word_sz = old->size(); - HeapRegion* const from_region = _g1h->heap_region_containing_raw(old); + HeapRegion* const from_region = _g1h->heap_region_containing(old); // +1 to make the -1 indexes valid... const int young_index = from_region->young_index_in_cset()+1; assert( (from_region->is_young() && young_index > 0) || @@ -294,9 +294,9 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, if (G1StringDedup::is_enabled()) { const bool is_from_young = state.is_young(); const bool is_to_young = dest_state.is_young(); - assert(is_from_young == _g1h->heap_region_containing_raw(old)->is_young(), + assert(is_from_young == _g1h->heap_region_containing(old)->is_young(), "sanity"); - assert(is_to_young == _g1h->heap_region_containing_raw(obj)->is_young(), + assert(is_to_young == _g1h->heap_region_containing(obj)->is_young(), "sanity"); G1StringDedup::enqueue_from_evacuation(is_from_young, is_to_young, @@ -314,7 +314,7 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, oop* old_p = set_partial_array_mask(old); push_on_queue(old_p); } else { - HeapRegion* const to_region = _g1h->heap_region_containing_raw(obj_ptr); + HeapRegion* const to_region = _g1h->heap_region_containing(obj_ptr); _scanner.set_region(to_region); obj->oop_iterate_backwards(&_scanner); } diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp index e2a35812f84..ae4b08a72da 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp @@ -101,7 +101,7 @@ inline void G1ParScanThreadState::do_oop_partial_array(oop* p) { // so that the heap remains parsable in case of evacuation failure. to_obj_array->set_length(end); } - _scanner.set_region(_g1h->heap_region_containing_raw(to_obj)); + _scanner.set_region(_g1h->heap_region_containing(to_obj)); // Process indexes [start,end). It will also process the header // along with the first chunk (i.e., the chunk with start == 0). // Note that at this point the length field of to_obj_array is not @@ -115,10 +115,7 @@ inline void G1ParScanThreadState::do_oop_partial_array(oop* p) { template inline void G1ParScanThreadState::deal_with_reference(T* ref_to_scan) { if (!has_partial_array_mask(ref_to_scan)) { - // Note: we can use "raw" versions of "region_containing" because - // "obj_to_scan" is definitely in the heap, and is not in a - // humongous region. - HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan); + HeapRegion* r = _g1h->heap_region_containing(ref_to_scan); do_oop_evac(ref_to_scan, r); } else { do_oop_partial_array((oop*)ref_to_scan); diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index 700ae50610b..87605532e51 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -40,42 +40,13 @@ #include "utilities/intHisto.hpp" #include "utilities/stack.inline.hpp" -#define CARD_REPEAT_HISTO 0 - -#if CARD_REPEAT_HISTO -static size_t ct_freq_sz; -static jbyte* ct_freq = NULL; - -void init_ct_freq_table(size_t heap_sz_bytes) { - if (ct_freq == NULL) { - ct_freq_sz = heap_sz_bytes/CardTableModRefBS::card_size; - ct_freq = new jbyte[ct_freq_sz]; - for (size_t j = 0; j < ct_freq_sz; j++) ct_freq[j] = 0; - } -} - -void ct_freq_note_card(size_t index) { - assert(0 <= index && index < ct_freq_sz, "Bounds error."); - if (ct_freq[index] < 100) { ct_freq[index]++; } -} - -static IntHistogram card_repeat_count(10, 10); - -void ct_freq_update_histo_and_reset() { - for (size_t j = 0; j < ct_freq_sz; j++) { - card_repeat_count.add_entry(ct_freq[j]); - ct_freq[j] = 0; - } - -} -#endif - G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs) : _g1(g1), _conc_refine_cards(0), _ct_bs(ct_bs), _g1p(_g1->g1_policy()), _cg1r(g1->concurrent_g1_refine()), _cset_rs_update_cl(NULL), - _prev_period_summary() + _prev_period_summary(), + _into_cset_dirty_card_queue_set(false) { _cset_rs_update_cl = NEW_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, n_workers(), mtGC); for (uint i = 0; i < n_workers(); i++) { @@ -84,6 +55,15 @@ G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs) if (G1SummarizeRSetStats) { _prev_period_summary.initialize(this); } + // Initialize the card queue set used to hold cards containing + // references into the collection set. + _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code + DirtyCardQ_CBL_mon, + DirtyCardQ_FL_lock, + -1, // never trigger processing + -1, // no limit on length + Shared_DirtyCardQ_lock, + &JavaThread::dirty_card_queue_set()); } G1RemSet::~G1RemSet() { @@ -272,7 +252,7 @@ public: if (_g1rs->refine_card(card_ptr, worker_i, true)) { // 'card_ptr' contains references that point into the collection // set. We need to record the card in the DCQS - // (G1CollectedHeap::into_cset_dirty_card_queue_set()) + // (_into_cset_dirty_card_queue_set) // that's used for that purpose. // // Enqueue the card @@ -302,10 +282,6 @@ void G1RemSet::cleanupHRRS() { size_t G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc, CodeBlobClosure* heap_region_codeblobs, uint worker_i) { -#if CARD_REPEAT_HISTO - ct_freq_update_histo_and_reset(); -#endif - // We cache the value of 'oc' closure into the appropriate slot in the // _cset_rs_update_cl for this worker assert(worker_i < n_workers(), "sanity"); @@ -320,7 +296,7 @@ size_t G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc, // are wholly 'free' of live objects. In the event of an evacuation // failure the cards/buffers in this queue set are passed to the // DirtyCardQueueSet that is used to manage RSet updates - DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set()); + DirtyCardQueue into_cset_dcq(&_into_cset_dirty_card_queue_set); updateRS(&into_cset_dcq, worker_i); size_t cards_scanned = scanRS(oc, heap_region_codeblobs, worker_i); @@ -343,7 +319,7 @@ void G1RemSet::cleanup_after_oops_into_collection_set_do() { // Set all cards back to clean. _g1->cleanUpCardTable(); - DirtyCardQueueSet& into_cset_dcqs = _g1->into_cset_dirty_card_queue_set(); + DirtyCardQueueSet& into_cset_dcqs = _into_cset_dirty_card_queue_set; int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num(); if (_g1->evacuation_failed()) { @@ -359,10 +335,10 @@ void G1RemSet::cleanup_after_oops_into_collection_set_do() { // Free any completed buffers in the DirtyCardQueueSet used to hold cards // which contain references that point into the collection. - _g1->into_cset_dirty_card_queue_set().clear(); - assert(_g1->into_cset_dirty_card_queue_set().completed_buffers_num() == 0, + _into_cset_dirty_card_queue_set.clear(); + assert(_into_cset_dirty_card_queue_set.completed_buffers_num() == 0, "all buffers should be freed"); - _g1->into_cset_dirty_card_queue_set().clear_n_completed_buffers(); + _into_cset_dirty_card_queue_set.clear_n_completed_buffers(); } class ScrubRSClosure: public HeapRegionClosure { @@ -498,11 +474,6 @@ bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i, HeapWord* end = start + CardTableModRefBS::card_size_in_words; MemRegion dirtyRegion(start, end); -#if CARD_REPEAT_HISTO - init_ct_freq_table(_g1->max_capacity()); - ct_freq_note_card(_ct_bs->index_for(start)); -#endif - G1ParPushHeapRSClosure* oops_in_heap_closure = NULL; if (check_for_refs_into_cset) { // ConcurrentG1RefineThreads have worker numbers larger than what @@ -607,12 +578,6 @@ void G1RemSet::print_summary_info(G1RemSetSummary * summary, const char * header gclog_or_tty->print_cr("%s", header); } -#if CARD_REPEAT_HISTO - gclog_or_tty->print_cr("\nG1 card_repeat count histogram: "); - gclog_or_tty->print_cr(" # of repeats --> # of cards with that number."); - card_repeat_count.print_on(gclog_or_tty); -#endif - summary->print_on(gclog_or_tty); } @@ -631,9 +596,9 @@ void G1RemSet::prepare_for_verify() { bool use_hot_card_cache = hot_card_cache->use_cache(); hot_card_cache->set_use_cache(false); - DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set()); + DirtyCardQueue into_cset_dcq(&_into_cset_dirty_card_queue_set); updateRS(&into_cset_dcq, 0); - _g1->into_cset_dirty_card_queue_set().clear(); + _into_cset_dirty_card_queue_set.clear(); hot_card_cache->set_use_cache(use_hot_card_cache); assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp index 7a278ba55b5..1ecb25c27dc 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp @@ -41,6 +41,13 @@ class G1ParPushHeapRSClosure; class G1RemSet: public CHeapObj { private: G1RemSetSummary _prev_period_summary; + + // A DirtyCardQueueSet that is used to hold cards that contain + // references into the current collection set. This is used to + // update the remembered sets of the regions in the collection + // set in the event of an evacuation failure. + DirtyCardQueueSet _into_cset_dirty_card_queue_set; + protected: G1CollectedHeap* _g1; size_t _conc_refine_cards; diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.inline.hpp b/hotspot/src/share/vm/gc/g1/g1RemSet.inline.hpp index 4fd438ab61f..af8f2e96f16 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.inline.hpp @@ -60,7 +60,7 @@ inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, uint tid) { assert(_g1->is_in_reserved(obj), "must be in heap"); #endif // ASSERT - assert(from == NULL || from->is_in_reserved(p), "p is not in from"); + assert(from->is_in_reserved(p) || from->is_starts_humongous(), "p is not in from"); HeapRegion* to = _g1->heap_region_containing(obj); if (from != to) { diff --git a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp index 36bb3d8c062..77b9957b9bf 100644 --- a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp @@ -26,7 +26,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/heapRegion.hpp" -#include "gc/g1/satbQueue.hpp" +#include "gc/g1/satbMarkQueue.hpp" #include "gc/shared/memset_with_concurrent_readers.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.inline.hpp" @@ -188,21 +188,6 @@ G1SATBCardTableLoggingModRefBS::write_ref_field_work(void* field, } } -void -G1SATBCardTableLoggingModRefBS::write_ref_field_static(void* field, - oop new_val) { - uintptr_t field_uint = (uintptr_t)field; - uintptr_t new_val_uint = cast_from_oop(new_val); - uintptr_t comb = field_uint ^ new_val_uint; - comb = comb >> HeapRegion::LogOfHRGrainBytes; - if (comb == 0) return; - if (new_val == NULL) return; - // Otherwise, log it. - G1SATBCardTableLoggingModRefBS* g1_bs = - barrier_set_cast(G1CollectedHeap::heap()->barrier_set()); - g1_bs->write_ref_field_work(field, new_val, false); -} - void G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr, bool whole_heap) { volatile jbyte* byte = byte_for(mr.start()); diff --git a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp index 6f5e8868156..d08d36f43ca 100644 --- a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp +++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp @@ -56,21 +56,15 @@ public: virtual bool has_write_ref_pre_barrier() { return true; } - // This notes that we don't need to access any BarrierSet data - // structures, so this can be called from a static context. - template static void write_ref_field_pre_static(T* field, oop newVal) { + // We export this to make it available in cases where the static + // type of the barrier set is known. Note that it is non-virtual. + template inline void inline_write_ref_field_pre(T* field, oop newVal) { T heap_oop = oopDesc::load_heap_oop(field); if (!oopDesc::is_null(heap_oop)) { enqueue(oopDesc::decode_heap_oop(heap_oop)); } } - // We export this to make it available in cases where the static - // type of the barrier set is known. Note that it is non-virtual. - template inline void inline_write_ref_field_pre(T* field, oop newVal) { - write_ref_field_pre_static(field, newVal); - } - // These are the more general virtual versions. virtual void write_ref_field_pre_work(oop* field, oop new_val) { inline_write_ref_field_pre(field, new_val); @@ -173,9 +167,6 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS { virtual void resize_covered_region(MemRegion new_region) { ShouldNotReachHere(); } - // Can be called from static contexts. - static void write_ref_field_static(void* field, oop new_val); - // NB: if you do a whole-heap invalidation, the "usual invariant" defined // above no longer applies. void invalidate(MemRegion mr, bool whole_heap = false); diff --git a/hotspot/src/share/vm/gc/g1/g1StringDedup.cpp b/hotspot/src/share/vm/gc/g1/g1StringDedup.cpp index 9a19c9f9431..fc6ad1bf116 100644 --- a/hotspot/src/share/vm/gc/g1/g1StringDedup.cpp +++ b/hotspot/src/share/vm/gc/g1/g1StringDedup.cpp @@ -52,7 +52,7 @@ void G1StringDedup::stop() { bool G1StringDedup::is_candidate_from_mark(oop obj) { if (java_lang_String::is_instance_inlined(obj)) { - bool from_young = G1CollectedHeap::heap()->heap_region_containing_raw(obj)->is_young(); + bool from_young = G1CollectedHeap::heap()->heap_region_containing(obj)->is_young(); if (from_young && obj->age() < StringDeduplicationAgeThreshold) { // Candidate found. String is being evacuated from young to old but has not // reached the deduplication age threshold, i.e. has not previously been a diff --git a/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp index 202bf8f6f9f..276cbabeca7 100644 --- a/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp +++ b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp @@ -198,10 +198,11 @@ void G1StringDedupTable::create() { _table = new G1StringDedupTable(_min_size); } -void G1StringDedupTable::add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list) { +void G1StringDedupTable::add(typeArrayOop value, bool latin1, unsigned int hash, G1StringDedupEntry** list) { G1StringDedupEntry* entry = _entry_cache->alloc(); entry->set_obj(value); entry->set_hash(hash); + entry->set_latin1(latin1); entry->set_next(*list); *list = entry; _entries++; @@ -226,15 +227,15 @@ void G1StringDedupTable::transfer(G1StringDedupEntry** pentry, G1StringDedupTabl bool G1StringDedupTable::equals(typeArrayOop value1, typeArrayOop value2) { return (value1 == value2 || (value1->length() == value2->length() && - (!memcmp(value1->base(T_CHAR), - value2->base(T_CHAR), - value1->length() * sizeof(jchar))))); + (!memcmp(value1->base(T_BYTE), + value2->base(T_BYTE), + value1->length() * sizeof(jbyte))))); } -typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, unsigned int hash, +typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, bool latin1, unsigned int hash, G1StringDedupEntry** list, uintx &count) { for (G1StringDedupEntry* entry = *list; entry != NULL; entry = entry->next()) { - if (entry->hash() == hash) { + if (entry->hash() == hash && entry->latin1() == latin1) { typeArrayOop existing_value = entry->obj(); if (equals(value, existing_value)) { // Match found @@ -248,13 +249,13 @@ typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, unsigned int hash, return NULL; } -typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, unsigned int hash) { +typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, bool latin1, unsigned int hash) { size_t index = hash_to_index(hash); G1StringDedupEntry** list = bucket(index); uintx count = 0; // Lookup in list - typeArrayOop existing_value = lookup(value, hash, list, count); + typeArrayOop existing_value = lookup(value, latin1, hash, list, count); // Check if rehash is needed if (count > _rehash_threshold) { @@ -263,7 +264,7 @@ typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, unsigne if (existing_value == NULL) { // Not found, add new entry - add(value, hash, list); + add(value, latin1, hash, list); // Update statistics _entries_added++; @@ -272,15 +273,24 @@ typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, unsigne return existing_value; } -unsigned int G1StringDedupTable::hash_code(typeArrayOop value) { +unsigned int G1StringDedupTable::hash_code(typeArrayOop value, bool latin1) { unsigned int hash; int length = value->length(); - const jchar* data = (jchar*)value->base(T_CHAR); - - if (use_java_hash()) { - hash = java_lang_String::hash_code(data, length); + if (latin1) { + const jbyte* data = (jbyte*)value->base(T_BYTE); + if (use_java_hash()) { + hash = java_lang_String::hash_code(data, length); + } else { + hash = AltHashing::murmur3_32(_table->_hash_seed, data, length); + } } else { - hash = AltHashing::murmur3_32(_table->_hash_seed, data, length); + length /= sizeof(jchar) / sizeof(jbyte); // Convert number of bytes to number of chars + const jchar* data = (jchar*)value->base(T_CHAR); + if (use_java_hash()) { + hash = java_lang_String::hash_code(data, length); + } else { + hash = AltHashing::murmur3_32(_table->_hash_seed, data, length); + } } return hash; @@ -299,6 +309,7 @@ void G1StringDedupTable::deduplicate(oop java_string, G1StringDedupStat& stat) { return; } + bool latin1 = java_lang_String::is_latin1(java_string); unsigned int hash = 0; if (use_java_hash()) { @@ -308,7 +319,7 @@ void G1StringDedupTable::deduplicate(oop java_string, G1StringDedupStat& stat) { if (hash == 0) { // Compute hash - hash = hash_code(value); + hash = hash_code(value, latin1); stat.inc_hashed(); if (use_java_hash() && hash != 0) { @@ -317,7 +328,7 @@ void G1StringDedupTable::deduplicate(oop java_string, G1StringDedupStat& stat) { } } - typeArrayOop existing_value = lookup_or_add(value, hash); + typeArrayOop existing_value = lookup_or_add(value, latin1, hash); if (existing_value == value) { // Same value, already known stat.inc_known(); @@ -459,7 +470,8 @@ uintx G1StringDedupTable::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* // destination partitions. finish_rehash() will do a single // threaded transfer of all entries. typeArrayOop value = (typeArrayOop)*p; - unsigned int hash = hash_code(value); + bool latin1 = (*entry)->latin1(); + unsigned int hash = hash_code(value, latin1); (*entry)->set_hash(hash); } @@ -523,7 +535,8 @@ void G1StringDedupTable::verify() { guarantee(G1CollectedHeap::heap()->is_in_reserved(value), "Object must be on the heap"); guarantee(!value->is_forwarded(), "Object must not be forwarded"); guarantee(value->is_typeArray(), "Object must be a typeArrayOop"); - unsigned int hash = hash_code(value); + bool latin1 = (*entry)->latin1(); + unsigned int hash = hash_code(value, latin1); guarantee((*entry)->hash() == hash, "Table entry has inorrect hash"); guarantee(_table->hash_to_index(hash) == bucket, "Table entry has incorrect index"); entry = (*entry)->next_addr(); @@ -536,10 +549,12 @@ void G1StringDedupTable::verify() { G1StringDedupEntry** entry1 = _table->bucket(bucket); while (*entry1 != NULL) { typeArrayOop value1 = (*entry1)->obj(); + bool latin1_1 = (*entry1)->latin1(); G1StringDedupEntry** entry2 = (*entry1)->next_addr(); while (*entry2 != NULL) { typeArrayOop value2 = (*entry2)->obj(); - guarantee(!equals(value1, value2), "Table entries must not have identical arrays"); + bool latin1_2 = (*entry2)->latin1(); + guarantee(latin1_1 != latin1_2 || !equals(value1, value2), "Table entries must not have identical arrays"); entry2 = (*entry2)->next_addr(); } entry1 = (*entry1)->next_addr(); diff --git a/hotspot/src/share/vm/gc/g1/g1StringDedupTable.hpp b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.hpp index 56f1c2d1c06..1aff126f813 100644 --- a/hotspot/src/share/vm/gc/g1/g1StringDedupTable.hpp +++ b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.hpp @@ -40,12 +40,14 @@ class G1StringDedupEntry : public CHeapObj { private: G1StringDedupEntry* _next; unsigned int _hash; + bool _latin1; typeArrayOop _obj; public: G1StringDedupEntry() : _next(NULL), _hash(0), + _latin1(false), _obj(NULL) { } @@ -69,6 +71,14 @@ public: _hash = hash; } + bool latin1() { + return _latin1; + } + + void set_latin1(bool latin1) { + _latin1 = latin1; + } + typeArrayOop obj() { return _obj; } @@ -152,7 +162,7 @@ private: } // Adds a new table entry to the given hash bucket. - void add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list); + void add(typeArrayOop value, bool latin1, unsigned int hash, G1StringDedupEntry** list); // Removes the given table entry from the table. void remove(G1StringDedupEntry** pentry, uint worker_id); @@ -162,20 +172,20 @@ private: // Returns an existing character array in the given hash bucket, or NULL // if no matching character array exists. - typeArrayOop lookup(typeArrayOop value, unsigned int hash, + typeArrayOop lookup(typeArrayOop value, bool latin1, unsigned int hash, G1StringDedupEntry** list, uintx &count); // Returns an existing character array in the table, or inserts a new // table entry if no matching character array exists. - typeArrayOop lookup_or_add_inner(typeArrayOop value, unsigned int hash); + typeArrayOop lookup_or_add_inner(typeArrayOop value, bool latin1, unsigned int hash); // Thread safe lookup or add of table entry - static typeArrayOop lookup_or_add(typeArrayOop value, unsigned int hash) { + static typeArrayOop lookup_or_add(typeArrayOop value, bool latin1, unsigned int hash) { // Protect the table from concurrent access. Also note that this lock // acts as a fence for _table, which could have been replaced by a new // instance if the table was resized or rehashed. MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag); - return _table->lookup_or_add_inner(value, hash); + return _table->lookup_or_add_inner(value, latin1, hash); } // Returns true if the hashtable is currently using a Java compatible @@ -188,7 +198,7 @@ private: // Computes the hash code for the given character array, using the // currently active hash function and hash seed. - static unsigned int hash_code(typeArrayOop value); + static unsigned int hash_code(typeArrayOop value, bool latin1); static uintx unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, size_t partition_begin, diff --git a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp new file mode 100644 index 00000000000..cc0506da12a --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015, 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 "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CollectorPolicy.hpp" +#include "gc/g1/g1YoungRemSetSamplingThread.hpp" +#include "gc/g1/suspendibleThreadSet.hpp" +#include "runtime/mutexLocker.hpp" + +void G1YoungRemSetSamplingThread::run() { + initialize_in_thread(); + wait_for_universe_init(); + + run_service(); + + terminate(); +} + +void G1YoungRemSetSamplingThread::stop() { + // it is ok to take late safepoints here, if needed + { + MutexLockerEx mu(Terminator_lock); + _should_terminate = true; + } + + stop_service(); + + { + MutexLockerEx mu(Terminator_lock); + while (!_has_terminated) { + Terminator_lock->wait(); + } + } +} + +G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : ConcurrentGCThread() { + _monitor = new Monitor(Mutex::nonleaf, + "G1YoungRemSetSamplingThread monitor", + true, + Monitor::_safepoint_check_never); + + create_and_start(); + + set_name("G1 Young RemSet Sampling"); +} + +void G1YoungRemSetSamplingThread::sleep_before_next_cycle() { + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + if (!_should_terminate) { + intx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? + _monitor->wait(Mutex::_no_safepoint_check_flag, waitms); + } +} + +void G1YoungRemSetSamplingThread::run_service() { + double vtime_start = os::elapsedVTime(); + + while (!_should_terminate) { + sample_young_list_rs_lengths(); + + if (os::supports_vtime()) { + _vtime_accum = (os::elapsedVTime() - vtime_start); + } else { + _vtime_accum = 0.0; + } + + sleep_before_next_cycle(); + } +} + +void G1YoungRemSetSamplingThread::stop_service() { + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + _monitor->notify(); +} + +void G1YoungRemSetSamplingThread::sample_young_list_rs_lengths() { + SuspendibleThreadSetJoiner sts; + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + G1CollectorPolicy* g1p = g1h->g1_policy(); + if (g1p->adaptive_young_list_length()) { + int regions_visited = 0; + g1h->young_list()->rs_length_sampling_init(); + while (g1h->young_list()->rs_length_sampling_more()) { + g1h->young_list()->rs_length_sampling_next(); + ++regions_visited; + + // we try to yield every time we visit 10 regions + if (regions_visited == 10) { + if (sts.should_yield()) { + sts.yield(); + // we just abandon the iteration + break; + } + regions_visited = 0; + } + } + + g1p->revise_young_list_target_length_if_necessary(); + } +} diff --git a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp new file mode 100644 index 00000000000..0e251451c02 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, 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_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP +#define SHARE_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP + +#include "gc/shared/concurrentGCThread.hpp" + +// The G1YoungRemSetSamplingThread is used to re-assess the validity of +// the prediction for the remembered set lengths of the young generation. +// +// At the end of the GC G1 determines the length of the young gen based on +// how much time the next GC can take, and when the next GC may occur +// according to the MMU. +// +// The assumption is that a significant part of the GC is spent on scanning +// the remembered sets (and many other components), so this thread constantly +// reevaluates the prediction for the remembered set scanning costs, and potentially +// G1CollectorPolicy resizes the young gen. This may do a premature GC or even +// increase the young gen size to keep pause time length goal. +class G1YoungRemSetSamplingThread: public ConcurrentGCThread { +private: + Monitor* _monitor; + + void sample_young_list_rs_lengths(); + + void run_service(); + void stop_service(); + + void sleep_before_next_cycle(); + + double _vtime_accum; // Accumulated virtual time. + +public: + G1YoungRemSetSamplingThread(); + double vtime_accum() { return _vtime_accum; } + + virtual void run(); + void stop(); +}; + +#endif /* SHARE_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP */ diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index 4297d76a5c7..a23edc0a5da 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -48,9 +48,6 @@ develop(bool, G1TraceMarkStackOverflow, false, \ "If true, extra debugging code for CM restart for ovflw.") \ \ - develop(bool, G1TraceHeapRegionRememberedSet, false, \ - "Enables heap region remembered set debug logs") \ - \ diagnostic(bool, G1SummarizeConcMark, false, \ "Summarize concurrent mark info") \ \ @@ -187,12 +184,6 @@ range(0, max_jint/wordSize) \ constraint(G1RSetSparseRegionEntriesConstraintFunc,AfterErgo) \ \ - develop(bool, G1RecordHRRSOops, false, \ - "When true, record recent calls to rem set operations.") \ - \ - develop(bool, G1RecordHRRSEvents, false, \ - "When true, record recent calls to rem set operations.") \ - \ develop(intx, G1MaxVerifyFailures, -1, \ "The maximum number of verification failures to print. " \ "-1 means print all.") \ @@ -228,10 +219,6 @@ develop(bool, G1HRRSFlushLogBuffersOnVerify, false, \ "Forces flushing of log buffers before verification.") \ \ - develop(bool, G1FailOnFPError, false, \ - "When set, G1 will fail when it encounters an FP 'error', " \ - "so as to allow debugging") \ - \ product(size_t, G1HeapRegionSize, 0, \ "Size of the G1 regions.") \ range(0, 32*M) \ diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.cpp b/hotspot/src/share/vm/gc/g1/heapRegion.cpp index 75e017ff3c2..6d6081f3af0 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp @@ -67,7 +67,7 @@ void HeapRegionDCTOC::walk_mem_region(MemRegion mr, // not considered dead, either because it is marked (in the mark bitmap) // or it was allocated after marking finished, then we add it. Otherwise // we can safely ignore the object. - if (!g1h->is_obj_dead(oop(cur), _hr)) { + if (!g1h->is_obj_dead(oop(cur))) { oop_size = oop(cur)->oop_iterate_size(_rs_scan, mr); } else { oop_size = _hr->block_size(cur); @@ -81,7 +81,7 @@ void HeapRegionDCTOC::walk_mem_region(MemRegion mr, HeapWord* next_obj = cur + oop_size; while (next_obj < top) { // Keep filtering the remembered set. - if (!g1h->is_obj_dead(cur_oop, _hr)) { + if (!g1h->is_obj_dead(cur_oop)) { // Bottom lies entirely below top, so we can call the // non-memRegion version of oop_iterate below. cur_oop->oop_iterate(_rs_scan); @@ -93,7 +93,7 @@ void HeapRegionDCTOC::walk_mem_region(MemRegion mr, } // Last object. Need to do dead-obj filtering here too. - if (!g1h->is_obj_dead(oop(cur), _hr)) { + if (!g1h->is_obj_dead(oop(cur))) { oop(cur)->oop_iterate(_rs_scan, mr); } } @@ -162,8 +162,6 @@ void HeapRegion::reset_after_compaction() { void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) { assert(_humongous_start_region == NULL, "we should have already filtered out humongous regions"); - assert(_end == orig_end(), - "we should have already filtered out humongous regions"); assert(!in_collection_set(), "Should not clear heap region %u in the collection set", hrm_index()); @@ -213,24 +211,18 @@ void HeapRegion::calc_gc_efficiency() { _gc_efficiency = (double) reclaimable_bytes() / region_elapsed_time_ms; } -void HeapRegion::set_starts_humongous(HeapWord* new_top, HeapWord* new_end) { +void HeapRegion::set_starts_humongous(HeapWord* obj_top) { assert(!is_humongous(), "sanity / pre-condition"); - assert(end() == orig_end(), - "Should be normal before the humongous object allocation"); assert(top() == bottom(), "should be empty"); - assert(bottom() <= new_top && new_top <= new_end, "pre-condition"); _type.set_starts_humongous(); _humongous_start_region = this; - set_end(new_end); - _offsets.set_for_starts_humongous(new_top); + _offsets.set_for_starts_humongous(obj_top); } void HeapRegion::set_continues_humongous(HeapRegion* first_hr) { assert(!is_humongous(), "sanity / pre-condition"); - assert(end() == orig_end(), - "Should be normal before the humongous object allocation"); assert(top() == bottom(), "should be empty"); assert(first_hr->is_starts_humongous(), "pre-condition"); @@ -241,18 +233,6 @@ void HeapRegion::set_continues_humongous(HeapRegion* first_hr) { void HeapRegion::clear_humongous() { assert(is_humongous(), "pre-condition"); - if (is_starts_humongous()) { - assert(top() <= end(), "pre-condition"); - set_end(orig_end()); - if (top() > end()) { - // at least one "continues humongous" region after it - set_top(end()); - } - } else { - // continues humongous - assert(end() == orig_end(), "sanity"); - } - assert(capacity() == HeapRegion::GrainBytes, "pre-condition"); _humongous_start_region = NULL; } @@ -290,11 +270,6 @@ void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) { hr_clear(false /*par*/, false /*clear_space*/); set_top(bottom()); record_timestamp(); - - assert(mr.end() == orig_end(), - "Given region end address " PTR_FORMAT " should match exactly " - "bottom plus one region size, i.e. " PTR_FORMAT, - p2i(mr.end()), p2i(orig_end())); } CompactibleSpace* HeapRegion::next_compaction_space() const { @@ -660,7 +635,7 @@ public: void print_object(outputStream* out, oop obj) { #ifdef PRODUCT Klass* k = obj->klass(); - const char* class_name = InstanceKlass::cast(k)->external_name(); + const char* class_name = k->external_name(); out->print_cr("class name %s", class_name); #else // PRODUCT obj->print_on(out); @@ -832,7 +807,14 @@ void HeapRegion::verify(VerifyOption vo, _offsets.verify(); } - if (p != top()) { + if (is_region_humongous) { + oop obj = oop(this->humongous_start_region()->bottom()); + if ((HeapWord*)obj > bottom() || (HeapWord*)obj + obj->size() < bottom()) { + gclog_or_tty->print_cr("this humongous region is not part of its' humongous object " PTR_FORMAT, p2i(obj)); + } + } + + if (!is_region_humongous && p != top()) { gclog_or_tty->print_cr("end of last object " PTR_FORMAT " " "does not match top " PTR_FORMAT, p2i(p), p2i(top())); *failures = true; @@ -840,7 +822,6 @@ void HeapRegion::verify(VerifyOption vo, } HeapWord* the_end = end(); - assert(p == top(), "it should still hold"); // Do some extra BOT consistency checking for addresses in the // range [top, end). BOT look-ups in this range should yield // top. No point in doing that if top == end (there's nothing there). @@ -931,6 +912,7 @@ void G1OffsetTableContigSpace::set_bottom(HeapWord* new_bottom) { } void G1OffsetTableContigSpace::set_end(HeapWord* new_end) { + assert(new_end == _bottom + HeapRegion::GrainWords, "set_end should only ever be set to _bottom + HeapRegion::GrainWords"); Space::set_end(new_end); _offsets.resize(new_end - bottom()); } diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.hpp b/hotspot/src/share/vm/gc/g1/heapRegion.hpp index e43b2e62d6d..eba1934dda0 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp @@ -43,6 +43,15 @@ // The solution is to remove this method from the definition // of a Space. +// Each heap region is self contained. top() and end() can never +// be set beyond the end of the region. For humongous objects, +// the first region is a StartsHumongous region. If the humongous +// object is larger than a heap region, the following regions will +// be of type ContinuesHumongous. In this case the top() of the +// StartHumongous region and all ContinuesHumongous regions except +// the last will point to their own end. For the last ContinuesHumongous +// region, top() will equal the object's top. + class G1CollectedHeap; class HeapRegionRemSet; class HeapRegionRemSetIterator; @@ -389,8 +398,6 @@ class HeapRegion: public G1OffsetTableContigSpace { size_t garbage_bytes() { size_t used_at_mark_start_bytes = (prev_top_at_mark_start() - bottom()) * HeapWordSize; - assert(used_at_mark_start_bytes >= marked_bytes(), - "Can't mark more than we have."); return used_at_mark_start_bytes - marked_bytes(); } @@ -409,7 +416,6 @@ class HeapRegion: public G1OffsetTableContigSpace { void add_to_marked_bytes(size_t incr_bytes) { _next_marked_bytes = _next_marked_bytes + incr_bytes; - assert(_next_marked_bytes <= used(), "invariant" ); } void zero_marked_bytes() { @@ -445,57 +451,13 @@ class HeapRegion: public G1OffsetTableContigSpace { return _humongous_start_region; } - // Return the number of distinct regions that are covered by this region: - // 1 if the region is not humongous, >= 1 if the region is humongous. - uint region_num() const { - if (!is_humongous()) { - return 1U; - } else { - assert(is_starts_humongous(), "doesn't make sense on HC regions"); - assert(capacity() % HeapRegion::GrainBytes == 0, "sanity"); - return (uint) (capacity() >> HeapRegion::LogOfHRGrainBytes); - } - } - - // Return the index + 1 of the last HC regions that's associated - // with this HS region. - uint last_hc_index() const { - assert(is_starts_humongous(), "don't call this otherwise"); - return hrm_index() + region_num(); - } - - // Same as Space::is_in_reserved, but will use the original size of the region. - // The original size is different only for start humongous regions. They get - // their _end set up to be the end of the last continues region of the - // corresponding humongous object. - bool is_in_reserved_raw(const void* p) const { - return _bottom <= p && p < orig_end(); - } - // Makes the current region be a "starts humongous" region, i.e., // the first region in a series of one or more contiguous regions - // that will contain a single "humongous" object. The two parameters - // are as follows: + // that will contain a single "humongous" object. // - // new_top : The new value of the top field of this region which - // points to the end of the humongous object that's being - // allocated. If there is more than one region in the series, top - // will lie beyond this region's original end field and on the last - // region in the series. - // - // new_end : The new value of the end field of this region which - // points to the end of the last region in the series. If there is - // one region in the series (namely: this one) end will be the same - // as the original end of this region. - // - // Updating top and end as described above makes this region look as - // if it spans the entire space taken up by all the regions in the - // series and an single allocation moved its top to new_top. This - // ensures that the space (capacity / allocated) taken up by all - // humongous regions can be calculated by just looking at the - // "starts humongous" regions and by ignoring the "continues - // humongous" regions. - void set_starts_humongous(HeapWord* new_top, HeapWord* new_end); + // obj_top : points to the end of the humongous object that's being + // allocated. + void set_starts_humongous(HeapWord* obj_top); // Makes the current region be a "continues humongous' // region. first_hr is the "start humongous" region of the series @@ -566,9 +528,6 @@ class HeapRegion: public G1OffsetTableContigSpace { void set_next_dirty_cards_region(HeapRegion* hr) { _next_dirty_cards_region = hr; } bool is_on_dirty_cards_region_list() const { return get_next_dirty_cards_region() != NULL; } - // For the start region of a humongous sequence, it's original end(). - HeapWord* orig_end() const { return _bottom + GrainWords; } - // Reset HR stuff to default values. void hr_clear(bool par, bool clear_space, bool locked = false); void par_clear(); @@ -614,8 +573,8 @@ class HeapRegion: public G1OffsetTableContigSpace { bool is_marked() { return _prev_top_at_mark_start != bottom(); } void reset_during_compaction() { - assert(is_starts_humongous(), - "should only be called for starts humongous regions"); + assert(is_humongous(), + "should only be called for humongous regions"); zero_marked_bytes(); init_top_at_mark_start(); diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp b/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp index 1b2fada7a23..245bd8ebfdf 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp @@ -115,6 +115,11 @@ G1OffsetTableContigSpace::block_start_const(const void* p) const { inline bool HeapRegion::block_is_obj(const HeapWord* p) const { G1CollectedHeap* g1h = G1CollectedHeap::heap(); + + if (!this->is_in(p)) { + assert(is_continues_humongous(), "This case can only happen for humongous regions"); + return (p == humongous_start_region()->bottom()); + } if (ClassUnloadingWithConcurrentMark) { return !g1h->is_obj_dead(oop(p), this); } @@ -176,10 +181,6 @@ inline void HeapRegion::note_end_of_marking() { _prev_top_at_mark_start = _next_top_at_mark_start; _prev_marked_bytes = _next_marked_bytes; _next_marked_bytes = 0; - - assert(_prev_marked_bytes <= - (size_t) pointer_delta(prev_top_at_mark_start(), bottom()) * - HeapWordSize, "invariant"); } inline void HeapRegion::note_start_of_copying(bool during_initial_mark) { diff --git a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp index 56e1234113a..f0452bc693b 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp @@ -343,63 +343,18 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, Heap continue; } HeapRegion* r = _regions.get_by_index(index); - // We'll ignore "continues humongous" regions (we'll process them - // when we come across their corresponding "start humongous" - // region) and regions already claimed. + // We'll ignore regions already claimed. // However, if the iteration is specified as concurrent, the values for // is_starts_humongous and is_continues_humongous can not be trusted, // and we should just blindly iterate over regions regardless of their // humongous status. - if (hrclaimer->is_region_claimed(index) || (!concurrent && r->is_continues_humongous())) { + if (hrclaimer->is_region_claimed(index)) { continue; } // OK, try to claim it if (!hrclaimer->claim_region(index)) { continue; } - // Success! - // As mentioned above, special treatment of humongous regions can only be - // done if we are iterating non-concurrently. - if (!concurrent && r->is_starts_humongous()) { - // If the region is "starts humongous" we'll iterate over its - // "continues humongous" first; in fact we'll do them - // first. The order is important. In one case, calling the - // closure on the "starts humongous" region might de-allocate - // and clear all its "continues humongous" regions and, as a - // result, we might end up processing them twice. So, we'll do - // them first (note: most closures will ignore them anyway) and - // then we'll do the "starts humongous" region. - for (uint ch_index = index + 1; ch_index < index + r->region_num(); ch_index++) { - HeapRegion* chr = _regions.get_by_index(ch_index); - - assert(chr->is_continues_humongous(), "Must be humongous region"); - assert(chr->humongous_start_region() == r, - "Must work on humongous continuation of the original start region " - PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr)); - assert(!hrclaimer->is_region_claimed(ch_index), - "Must not have been claimed yet because claiming of humongous continuation first claims the start region"); - - // Claim the region so no other worker tries to process the region. When a worker processes a - // starts_humongous region it may also process the associated continues_humongous regions. - // The continues_humongous regions can be changed to free regions. Unless this worker claims - // all of these regions, other workers might try claim and process these newly free regions. - bool claim_result = hrclaimer->claim_region(ch_index); - guarantee(claim_result, "We should always be able to claim the continuesHumongous part of the humongous object"); - - bool res2 = blk->doHeapRegion(chr); - if (res2) { - return; - } - - // Right now, this holds (i.e., no closure that actually - // does something with "continues humongous" regions - // clears them). We might have to weaken it in the future, - // but let's leave these two asserts here for extra safety. - assert(chr->is_continues_humongous(), "should still be the case"); - assert(chr->humongous_start_region() == r, "sanity"); - } - } - bool res = blk->doHeapRegion(r); if (res) { return; @@ -508,11 +463,7 @@ void HeapRegionManager::verify() { // this method may be called, we have only completed allocation of the regions, // but not put into a region set. prev_committed = true; - if (hr->is_starts_humongous()) { - prev_end = hr->orig_end(); - } else { - prev_end = hr->end(); - } + prev_end = hr->end(); } for (uint i = _allocated_heapregions_length; i < max_length(); i++) { guarantee(_regions.get_by_index(i) == NULL, "invariant i: %u", i); diff --git a/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp b/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp index 66f30fed49f..03bc3ed53b4 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp @@ -150,6 +150,10 @@ public: // is valid. inline HeapRegion* at(uint index) const; + // Return the next region (by index) that is part of the same + // humongous object that hr is part of. + inline HeapRegion* next_region_in_humongous(HeapRegion* hr) const; + // If addr is within the committed space return its corresponding // HeapRegion, otherwise return NULL. inline HeapRegion* addr_to_region(HeapWord* addr) const; diff --git a/hotspot/src/share/vm/gc/g1/heapRegionManager.inline.hpp b/hotspot/src/share/vm/gc/g1/heapRegionManager.inline.hpp index 1eb26d0aa47..67b31149b12 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.inline.hpp @@ -47,6 +47,18 @@ inline HeapRegion* HeapRegionManager::at(uint index) const { return hr; } +inline HeapRegion* HeapRegionManager::next_region_in_humongous(HeapRegion* hr) const { + uint index = hr->hrm_index(); + assert(is_available(index), "pre-condition"); + assert(hr->is_humongous(), "next_region_in_humongous should only be called for a humongous region."); + index++; + if (index < max_length() && is_available(index) && at(index)->is_continues_humongous()) { + return at(index); + } else { + return NULL; + } +} + inline void HeapRegionManager::insert_into_free_list(HeapRegion* hr) { _free_list.add_ordered(hr); } diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp index 3186ff9f311..1d14accec5f 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp @@ -89,14 +89,6 @@ protected: // Must make this robust in case "from" is not in "_hr", because of // concurrency. - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr(" PRT::Add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").", - p2i(from), - UseCompressedOops - ? p2i(oopDesc::load_decode_heap_oop((narrowOop*)from)) - : p2i(oopDesc::load_decode_heap_oop((oop*)from))); - } - HeapRegion* loc_hr = hr(); // If the test below fails, then this table was reused concurrently // with this operation. This is OK, since the old table was coarsened, @@ -105,7 +97,7 @@ protected: // now reused for the corresponding start humongous region, we need to // make sure that we detect this. Thus, we call is_in_reserved_raw() // instead of just is_in_reserved() here. - if (loc_hr->is_in_reserved_raw(from)) { + if (loc_hr->is_in_reserved(from)) { size_t hw_offset = pointer_delta((HeapWord*)from, loc_hr->bottom()); CardIdx_t from_card = (CardIdx_t) hw_offset >> (CardTableModRefBS::card_shift - LogHeapWordSize); @@ -408,39 +400,19 @@ void FromCardCache::clear(uint region_idx) { void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { uint cur_hrm_ind = _hr->hrm_index(); - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").", - p2i(from), - UseCompressedOops - ? p2i(oopDesc::load_decode_heap_oop((narrowOop*)from)) - : p2i(oopDesc::load_decode_heap_oop((oop*)from))); - } - int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift); - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)", - p2i(_hr->bottom()), from_card, - FromCardCache::at(tid, cur_hrm_ind)); - } - if (FromCardCache::contains_or_replace(tid, cur_hrm_ind, from_card)) { - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr(" from-card cache hit."); - } assert(contains_reference(from), "We just added it!"); return; } // Note that this may be a continued H region. - HeapRegion* from_hr = _g1h->heap_region_containing_raw(from); + HeapRegion* from_hr = _g1h->heap_region_containing(from); RegionIdx_t from_hrm_ind = (RegionIdx_t) from_hr->hrm_index(); // If the region is already coarsened, return. if (_coarse_map.at(from_hrm_ind)) { - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr(" coarse map hit."); - } assert(contains_reference(from), "We just added it!"); return; } @@ -462,27 +434,8 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { "Must be in range."); if (G1HRRSUseSparseTable && _sparse_table.add_card(from_hrm_ind, card_index)) { - if (G1RecordHRRSOops) { - HeapRegionRemSet::record(_hr, from); - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print(" Added card " PTR_FORMAT " to region " - "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n", - align_size_down(uintptr_t(from), - CardTableModRefBS::card_size), - p2i(_hr->bottom()), p2i(from)); - } - } - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr(" added card to sparse table."); - } assert(contains_reference_locked(from), "We just added it!"); return; - } else { - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr(" [tid %u] sparse table entry " - "overflow(f: %d, t: %u)", - tid, from_hrm_ind, cur_hrm_ind); - } } if (_n_fine_entries == _max_fine_entries) { @@ -531,17 +484,6 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { assert(prt != NULL, "Inv"); prt->add_reference(from); - - if (G1RecordHRRSOops) { - HeapRegionRemSet::record(_hr, from); - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print("Added card " PTR_FORMAT " to region " - "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n", - align_size_down(uintptr_t(from), - CardTableModRefBS::card_size), - p2i(_hr->bottom()), p2i(from)); - } - } assert(contains_reference(from), "We just added it!"); } @@ -563,7 +505,7 @@ PerRegionTable* OtherRegionsTable::delete_region_table() { assert(_n_fine_entries == _max_fine_entries, "Precondition"); PerRegionTable* max = NULL; jint max_occ = 0; - PerRegionTable** max_prev; + PerRegionTable** max_prev = NULL; size_t max_ind; size_t i = _fine_eviction_start; @@ -599,19 +541,13 @@ PerRegionTable* OtherRegionsTable::delete_region_table() { } guarantee(max != NULL, "Since _n_fine_entries > 0"); + guarantee(max_prev != NULL, "Since max != NULL."); // Set the corresponding coarse bit. size_t max_hrm_index = (size_t) max->hr()->hrm_index(); if (!_coarse_map.at(max_hrm_index)) { _coarse_map.at_put(max_hrm_index, true); _n_coarse_entries++; - if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print("Coarsened entry in region [" PTR_FORMAT "...] " - "for region [" PTR_FORMAT "...] (" SIZE_FORMAT " coarse entries).\n", - p2i(_hr->bottom()), - p2i(max->hr()->bottom()), - _n_coarse_entries); - } } // Unsplice. @@ -785,7 +721,7 @@ bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const { } bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const { - HeapRegion* hr = _g1h->heap_region_containing_raw(from); + HeapRegion* hr = _g1h->heap_region_containing(from); RegionIdx_t hr_ind = (RegionIdx_t) hr->hrm_index(); // Is this region in the coarse map? if (_coarse_map.at(hr_ind)) return true; @@ -1070,99 +1006,6 @@ bool HeapRegionRemSetIterator::has_next(size_t& card_index) { return false; } - - -OopOrNarrowOopStar* HeapRegionRemSet::_recorded_oops = NULL; -HeapWord** HeapRegionRemSet::_recorded_cards = NULL; -HeapRegion** HeapRegionRemSet::_recorded_regions = NULL; -int HeapRegionRemSet::_n_recorded = 0; - -HeapRegionRemSet::Event* HeapRegionRemSet::_recorded_events = NULL; -int* HeapRegionRemSet::_recorded_event_index = NULL; -int HeapRegionRemSet::_n_recorded_events = 0; - -void HeapRegionRemSet::record(HeapRegion* hr, OopOrNarrowOopStar f) { - if (_recorded_oops == NULL) { - assert(_n_recorded == 0 - && _recorded_cards == NULL - && _recorded_regions == NULL, - "Inv"); - _recorded_oops = NEW_C_HEAP_ARRAY(OopOrNarrowOopStar, MaxRecorded, mtGC); - _recorded_cards = NEW_C_HEAP_ARRAY(HeapWord*, MaxRecorded, mtGC); - _recorded_regions = NEW_C_HEAP_ARRAY(HeapRegion*, MaxRecorded, mtGC); - } - if (_n_recorded == MaxRecorded) { - gclog_or_tty->print_cr("Filled up 'recorded' (%d).", MaxRecorded); - } else { - _recorded_cards[_n_recorded] = - (HeapWord*)align_size_down(uintptr_t(f), - CardTableModRefBS::card_size); - _recorded_oops[_n_recorded] = f; - _recorded_regions[_n_recorded] = hr; - _n_recorded++; - } -} - -void HeapRegionRemSet::record_event(Event evnt) { - if (!G1RecordHRRSEvents) return; - - if (_recorded_events == NULL) { - assert(_n_recorded_events == 0 - && _recorded_event_index == NULL, - "Inv"); - _recorded_events = NEW_C_HEAP_ARRAY(Event, MaxRecordedEvents, mtGC); - _recorded_event_index = NEW_C_HEAP_ARRAY(int, MaxRecordedEvents, mtGC); - } - if (_n_recorded_events == MaxRecordedEvents) { - gclog_or_tty->print_cr("Filled up 'recorded_events' (%d).", MaxRecordedEvents); - } else { - _recorded_events[_n_recorded_events] = evnt; - _recorded_event_index[_n_recorded_events] = _n_recorded; - _n_recorded_events++; - } -} - -void HeapRegionRemSet::print_event(outputStream* str, Event evnt) { - switch (evnt) { - case Event_EvacStart: - str->print("Evac Start"); - break; - case Event_EvacEnd: - str->print("Evac End"); - break; - case Event_RSUpdateEnd: - str->print("RS Update End"); - break; - } -} - -void HeapRegionRemSet::print_recorded() { - int cur_evnt = 0; - Event cur_evnt_kind; - int cur_evnt_ind = 0; - if (_n_recorded_events > 0) { - cur_evnt_kind = _recorded_events[cur_evnt]; - cur_evnt_ind = _recorded_event_index[cur_evnt]; - } - - for (int i = 0; i < _n_recorded; i++) { - while (cur_evnt < _n_recorded_events && i == cur_evnt_ind) { - gclog_or_tty->print("Event: "); - print_event(gclog_or_tty, cur_evnt_kind); - gclog_or_tty->cr(); - cur_evnt++; - if (cur_evnt < MaxRecordedEvents) { - cur_evnt_kind = _recorded_events[cur_evnt]; - cur_evnt_ind = _recorded_event_index[cur_evnt]; - } - } - gclog_or_tty->print("Added card " PTR_FORMAT " to region [" PTR_FORMAT "...]" - " for ref " PTR_FORMAT ".\n", - p2i(_recorded_cards[i]), p2i(_recorded_regions[i]->bottom()), - p2i(_recorded_oops[i])); - } -} - void HeapRegionRemSet::reset_for_cleanup_tasks() { SparsePRT::reset_for_cleanup_tasks(); } diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp index 3b07c65d1bf..4b7dcf67bda 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp @@ -220,11 +220,6 @@ class HeapRegionRemSet : public CHeapObj { friend class VMStructs; friend class HeapRegionRemSetIterator; -public: - enum Event { - Event_EvacStart, Event_EvacEnd, Event_RSUpdateEnd - }; - private: G1BlockOffsetSharedArray* _bosa; @@ -240,21 +235,6 @@ private: volatile ParIterState _iter_state; volatile size_t _iter_claimed; - // Unused unless G1RecordHRRSOops is true. - - static const int MaxRecorded = 1000000; - static OopOrNarrowOopStar* _recorded_oops; - static HeapWord** _recorded_cards; - static HeapRegion** _recorded_regions; - static int _n_recorded; - - static const int MaxRecordedEvents = 1000; - static Event* _recorded_events; - static int* _recorded_event_index; - static int _n_recorded_events; - - static void print_event(outputStream* str, Event evnt); - public: HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr); @@ -404,10 +384,6 @@ public: } #endif - static void record(HeapRegion* hr, OopOrNarrowOopStar f); - static void print_recorded(); - static void record_event(Event evnt); - // These are wrappers for the similarly-named methods on // SparsePRT. Look at sparsePRT.hpp for more details. static void reset_for_cleanup_tasks(); diff --git a/hotspot/src/share/vm/gc/g1/heapRegionSet.cpp b/hotspot/src/share/vm/gc/g1/heapRegionSet.cpp index ce56dc3cc2e..fc18e92c9cb 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionSet.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionSet.cpp @@ -29,12 +29,6 @@ uint FreeRegionList::_unrealistically_long_length = 0; -void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) { - msg->append("[%s] %s ln: %u cy: " SIZE_FORMAT, - name(), message, length(), total_capacity_bytes()); - fill_in_ext_msg_extra(msg); -} - #ifndef PRODUCT void HeapRegionSetBase::verify_region(HeapRegion* hr) { assert(hr->containing_set() == this, "Inconsistent containing set for %u", hr->hrm_index()); @@ -55,16 +49,15 @@ void HeapRegionSetBase::verify() { // verification might fail and send us on a wild goose chase. check_mt_safety(); - guarantee(( is_empty() && length() == 0 && total_capacity_bytes() == 0) || - (!is_empty() && length() > 0 && total_capacity_bytes() > 0) , - "%s", hrs_ext_msg(this, "invariant").buffer()); + guarantee_heap_region_set(( is_empty() && length() == 0 && total_capacity_bytes() == 0) || + (!is_empty() && length() > 0 && total_capacity_bytes() > 0) , + "invariant"); } void HeapRegionSetBase::verify_start() { // See comment in verify() about MT safety and verification. check_mt_safety(); - assert(!_verify_in_progress, - "%s", hrs_ext_msg(this, "verification should not be in progress").buffer()); + assert_heap_region_set(!_verify_in_progress, "verification should not be in progress"); // Do the basic verification first before we do the checks over the regions. HeapRegionSetBase::verify(); @@ -75,8 +68,7 @@ void HeapRegionSetBase::verify_start() { void HeapRegionSetBase::verify_end() { // See comment in verify() about MT safety and verification. check_mt_safety(); - assert(_verify_in_progress, - "%s", hrs_ext_msg(this, "verification should be in progress").buffer()); + assert_heap_region_set(_verify_in_progress, "verification should be in progress"); _verify_in_progress = false; } @@ -104,10 +96,6 @@ void FreeRegionList::set_unrealistically_long_length(uint len) { _unrealistically_long_length = len; } -void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { - msg->append(" hd: " PTR_FORMAT " tl: " PTR_FORMAT, p2i(_head), p2i(_tail)); -} - void FreeRegionList::remove_all() { check_mt_safety(); verify_optional(); @@ -151,7 +139,7 @@ void FreeRegionList::add_ordered(FreeRegionList* from_list) { #endif // ASSERT if (is_empty()) { - assert(length() == 0 && _tail == NULL, "%s", hrs_ext_msg(this, "invariant").buffer()); + assert_free_region_list(length() == 0 && _tail == NULL, "invariant"); _head = from_list->_head; _tail = from_list->_tail; } else { @@ -198,8 +186,8 @@ void FreeRegionList::add_ordered(FreeRegionList* from_list) { void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) { check_mt_safety(); - assert(num_regions >= 1, "%s", hrs_ext_msg(this, "pre-condition").buffer()); - assert(!is_empty(), "%s", hrs_ext_msg(this, "pre-condition").buffer()); + assert_free_region_list(num_regions >= 1, "pre-condition"); + assert_free_region_list(!is_empty(), "pre-condition"); verify_optional(); DEBUG_ONLY(uint old_length = length();) @@ -212,25 +200,25 @@ void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) { HeapRegion* prev = curr->prev(); assert(count < num_regions, - "%s", hrs_err_msg("[%s] should not come across more regions " - "pending for removal than num_regions: %u", - name(), num_regions).buffer()); + "[%s] should not come across more regions " + "pending for removal than num_regions: %u", + name(), num_regions); if (prev == NULL) { - assert(_head == curr, "%s", hrs_ext_msg(this, "invariant").buffer()); + assert_free_region_list(_head == curr, "invariant"); _head = next; } else { - assert(_head != curr, "%s", hrs_ext_msg(this, "invariant").buffer()); + assert_free_region_list(_head != curr, "invariant"); prev->set_next(next); } if (next == NULL) { - assert(_tail == curr, "%s", hrs_ext_msg(this, "invariant").buffer()); + assert_free_region_list(_tail == curr, "invariant"); _tail = prev; } else { - assert(_tail != curr, "%s", hrs_ext_msg(this, "invariant").buffer()); + assert_free_region_list(_tail != curr, "invariant"); next->set_prev(prev); } - if (_last = curr) { + if (_last == curr) { _last = NULL; } @@ -243,12 +231,12 @@ void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) { } assert(count == num_regions, - "%s", hrs_err_msg("[%s] count: %u should be == num_regions: %u", - name(), count, num_regions).buffer()); + "[%s] count: %u should be == num_regions: %u", + name(), count, num_regions); assert(length() + num_regions == old_length, - "%s", hrs_err_msg("[%s] new length should be consistent " - "new length: %u old length: %u num_regions: %u", - name(), length(), old_length, num_regions).buffer()); + "[%s] new length should be consistent " + "new length: %u old length: %u num_regions: %u", + name(), length(), old_length, num_regions); verify_optional(); } @@ -305,8 +293,8 @@ void FreeRegionList::verify_list() { count++; guarantee(count < _unrealistically_long_length, - "%s", hrs_err_msg("[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: " PTR_FORMAT " prev0: " PTR_FORMAT " " "prev1: " PTR_FORMAT " length: %u", - name(), count, p2i(curr), p2i(prev0), p2i(prev1), length()).buffer()); + "[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: " PTR_FORMAT " prev0: " PTR_FORMAT " " "prev1: " PTR_FORMAT " length: %u", + name(), count, p2i(curr), p2i(prev0), p2i(prev1), length()); if (curr->next() != NULL) { guarantee(curr->next()->prev() == curr, "Next or prev pointers messed up"); diff --git a/hotspot/src/share/vm/gc/g1/heapRegionSet.hpp b/hotspot/src/share/vm/gc/g1/heapRegionSet.hpp index f5325e552ee..c291a119e2a 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionSet.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionSet.hpp @@ -27,9 +27,24 @@ #include "gc/g1/heapRegion.hpp" -// Large buffer for some cases where the output might be larger than normal. -#define HRS_ERR_MSG_BUFSZ 512 -typedef FormatBuffer hrs_err_msg; +#define assert_heap_region_set(p, message) \ + do { \ + assert((p), "[%s] %s ln: %u cy: " SIZE_FORMAT, \ + name(), message, length(), total_capacity_bytes()); \ + } while (0) + +#define guarantee_heap_region_set(p, message) \ + do { \ + guarantee((p), "[%s] %s ln: %u cy: " SIZE_FORMAT, \ + name(), message, length(), total_capacity_bytes()); \ + } while (0) + +#define assert_free_region_list(p, message) \ + do { \ + assert((p), "[%s] %s ln: %u cy: " SIZE_FORMAT " hd: " PTR_FORMAT " tl: " PTR_FORMAT, \ + name(), message, length(), total_capacity_bytes(), p2i(_head), p2i(_tail)); \ + } while (0) + // Set verification will be forced either if someone defines // HEAP_REGION_SET_FORCE_VERIFY to be 1, or in builds in which @@ -38,8 +53,6 @@ typedef FormatBuffer hrs_err_msg; #define HEAP_REGION_SET_FORCE_VERIFY defined(ASSERT) #endif // HEAP_REGION_SET_FORCE_VERIFY -class hrs_ext_msg; - class HRSMtSafeChecker : public CHeapObj { public: virtual void check() = 0; @@ -112,8 +125,6 @@ protected: } } - virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { } - HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker); public: @@ -135,11 +146,6 @@ public: // from the set and tags the region appropriately. inline void remove(HeapRegion* hr); - // fill_in_ext_msg() writes the the values of the set's attributes - // in the custom err_msg (hrs_ext_msg). fill_in_ext_msg_extra() - // allows subclasses to append further information. - void fill_in_ext_msg(hrs_ext_msg* msg, const char* message); - virtual void verify(); void verify_start(); void verify_next_region(HeapRegion* hr); @@ -156,24 +162,13 @@ public: virtual void print_on(outputStream* out, bool print_contents = false); }; -// Customized err_msg for heap region sets. Apart from a -// assert/guarantee-specific message it also prints out the values of -// the fields of the associated set. This can be very helpful in -// diagnosing failures. -class hrs_ext_msg : public hrs_err_msg { -public: - hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("%s", "") { - set->fill_in_ext_msg(this, message); - } -}; - -#define hrs_assert_sets_match(_set1_, _set2_) \ - do { \ - assert(((_set1_)->regions_humongous() == \ - (_set2_)->regions_humongous()) && \ - ((_set1_)->regions_free() == (_set2_)->regions_free()), \ - hrs_err_msg("the contents of set %s and set %s should match", \ - (_set1_)->name(), (_set2_)->name())); \ +#define hrs_assert_sets_match(_set1_, _set2_) \ + do { \ + assert(((_set1_)->regions_humongous() == (_set2_)->regions_humongous()) && \ + ((_set1_)->regions_free() == (_set2_)->regions_free()), \ + "the contents of set %s and set %s should match", \ + (_set1_)->name(), \ + (_set2_)->name()); \ } while (0) // This class represents heap region sets whose members are not @@ -215,8 +210,6 @@ private: inline HeapRegion* remove_from_tail_impl(); protected: - virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg); - // See the comment for HeapRegionSetBase::clear() virtual void clear(); diff --git a/hotspot/src/share/vm/gc/g1/heapRegionSet.inline.hpp b/hotspot/src/share/vm/gc/g1/heapRegionSet.inline.hpp index fa370f059a9..f733d567f34 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionSet.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionSet.inline.hpp @@ -29,9 +29,9 @@ inline void HeapRegionSetBase::add(HeapRegion* hr) { check_mt_safety(); - assert(hr->containing_set() == NULL, "%s", hrs_ext_msg(this, "should not already have a containing set %u").buffer()); - assert(hr->next() == NULL, "%s", hrs_ext_msg(this, "should not already be linked").buffer()); - assert(hr->prev() == NULL, "%s", hrs_ext_msg(this, "should not already be linked").buffer()); + assert_heap_region_set(hr->containing_set() == NULL, "should not already have a containing set"); + assert_heap_region_set(hr->next() == NULL, "should not already be linked"); + assert_heap_region_set(hr->prev() == NULL, "should not already be linked"); _count.increment(1u, hr->capacity()); hr->set_containing_set(this); @@ -41,18 +41,18 @@ inline void HeapRegionSetBase::add(HeapRegion* hr) { inline void HeapRegionSetBase::remove(HeapRegion* hr) { check_mt_safety(); verify_region(hr); - assert(hr->next() == NULL, "%s", hrs_ext_msg(this, "should already be unlinked").buffer()); - assert(hr->prev() == NULL, "%s", hrs_ext_msg(this, "should already be unlinked").buffer()); + assert_heap_region_set(hr->next() == NULL, "should already be unlinked"); + assert_heap_region_set(hr->prev() == NULL, "should already be unlinked"); hr->set_containing_set(NULL); - assert(_count.length() > 0, "%s", hrs_ext_msg(this, "pre-condition").buffer()); + assert_heap_region_set(_count.length() > 0, "pre-condition"); _count.decrement(1u, hr->capacity()); } inline void FreeRegionList::add_ordered(HeapRegion* hr) { - assert((length() == 0 && _head == NULL && _tail == NULL && _last == NULL) || - (length() > 0 && _head != NULL && _tail != NULL), - "%s", hrs_ext_msg(this, "invariant").buffer()); + assert_free_region_list((length() == 0 && _head == NULL && _tail == NULL && _last == NULL) || + (length() > 0 && _head != NULL && _tail != NULL), + "invariant"); // add() will verify the region and check mt safety. add(hr); @@ -128,8 +128,7 @@ inline HeapRegion* FreeRegionList::remove_region(bool from_head) { if (is_empty()) { return NULL; } - assert(length() > 0 && _head != NULL && _tail != NULL, - "%s", hrs_ext_msg(this, "invariant").buffer()); + assert_free_region_list(length() > 0 && _head != NULL && _tail != NULL, "invariant"); HeapRegion* hr; diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp index 42aa91175b0..756b9599fb8 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp @@ -30,24 +30,25 @@ #include "runtime/mutexLocker.hpp" #include "runtime/thread.inline.hpp" -PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) : +PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) : _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active), - _perm(perm), _lock(NULL) + _permanent(permanent), _lock(NULL) {} PtrQueue::~PtrQueue() { - assert(_perm || (_buf == NULL), "queue must be flushed before delete"); + assert(_permanent || (_buf == NULL), "queue must be flushed before delete"); } void PtrQueue::flush_impl() { - if (!_perm && _buf != NULL) { + if (!_permanent && _buf != NULL) { if (_index == _sz) { // No work to do. qset()->deallocate_buffer(_buf); } else { // We must NULL out the unused entries, then enqueue. - for (size_t i = 0; i < _index; i += oopSize) { - _buf[byte_index_to_index((int)i)] = NULL; + size_t limit = byte_index_to_index(_index); + for (size_t i = 0; i < limit; ++i) { + _buf[i] = NULL; } qset()->enqueue_complete_buffer(_buf); } @@ -66,8 +67,8 @@ void PtrQueue::enqueue_known_active(void* ptr) { } assert(_index > 0, "postcondition"); - _index -= oopSize; - _buf[byte_index_to_index((int)_index)] = ptr; + _index -= sizeof(void*); + _buf[byte_index_to_index(_index)] = ptr; assert(_index <= _sz, "Invariant."); } @@ -100,6 +101,26 @@ PtrQueueSet::PtrQueueSet(bool notify_when_complete) : _fl_owner = this; } +PtrQueueSet::~PtrQueueSet() { + // There are presently only a couple (derived) instances ever + // created, and they are permanent, so no harm currently done by + // doing nothing here. +} + +void PtrQueueSet::initialize(Monitor* cbl_mon, + Mutex* fl_lock, + int process_completed_threshold, + int max_completed_queue, + PtrQueueSet *fl_owner) { + _max_completed_queue = max_completed_queue; + _process_completed_threshold = process_completed_threshold; + _completed_queue_padding = 0; + assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?"); + _cbl_mon = cbl_mon; + _fl_lock = fl_lock; + _fl_owner = (fl_owner != NULL) ? fl_owner : this; +} + void** PtrQueueSet::allocate_buffer() { assert(_sz > 0, "Didn't set a buffer size."); MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); @@ -233,7 +254,7 @@ void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) { if (_notify_when_complete) _cbl_mon->notify(); } - debug_only(assert_completed_buffer_list_len_correct_locked()); + DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); } int PtrQueueSet::completed_buffers_list_length() { @@ -258,7 +279,7 @@ void PtrQueueSet::assert_completed_buffer_list_len_correct_locked() { void PtrQueueSet::set_buffer_size(size_t sz) { assert(_sz == 0 && sz > 0, "Should be called only once."); - _sz = sz * oopSize; + _sz = sz * sizeof(void*); } // Merge lists of buffers. Notify the processing threads. diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp index b4071450f40..39f1c931e74 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp @@ -40,44 +40,49 @@ class PtrQueueSet; class PtrQueue VALUE_OBJ_CLASS_SPEC { friend class VMStructs; -protected: + // Noncopyable - not defined. + PtrQueue(const PtrQueue&); + PtrQueue& operator=(const PtrQueue&); + // The ptr queue set to which this queue belongs. - PtrQueueSet* _qset; + PtrQueueSet* const _qset; // Whether updates should be logged. bool _active; - // The buffer. - void** _buf; - // The index at which an object was last enqueued. Starts at "_sz" - // (indicating an empty buffer) and goes towards zero. - size_t _index; - - // The size of the buffer. - size_t _sz; - // If true, the queue is permanent, and doesn't need to deallocate // its buffer in the destructor (since that obtains a lock which may not // be legally locked by then. - bool _perm; + const bool _permanent; + +protected: + // The buffer. + void** _buf; + // The (byte) index at which an object was last enqueued. Starts at "_sz" + // (indicating an empty buffer) and goes towards zero. + size_t _index; + + // The (byte) size of the buffer. + size_t _sz; // If there is a lock associated with this buffer, this is that lock. Mutex* _lock; PtrQueueSet* qset() { return _qset; } - bool is_permanent() const { return _perm; } + bool is_permanent() const { return _permanent; } // Process queue entries and release resources, if not permanent. void flush_impl(); -public: // Initialize this queue to contain a null buffer, and be part of the // given PtrQueueSet. - PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false); + PtrQueue(PtrQueueSet* qset, bool permanent = false, bool active = false); // Requires queue flushed or permanent. ~PtrQueue(); +public: + // Associate a lock with a ptr queue. void set_lock(Mutex* lock) { _lock = lock; } @@ -129,13 +134,9 @@ public: bool is_active() { return _active; } - static int byte_index_to_index(int ind) { - assert((ind % oopSize) == 0, "Invariant."); - return ind / oopSize; - } - - static int index_to_byte_index(int byte_ind) { - return byte_ind * oopSize; + static size_t byte_index_to_index(size_t ind) { + assert((ind % sizeof(void*)) == 0, "Invariant."); + return ind / sizeof(void*); } // To support compiler. @@ -246,26 +247,21 @@ protected: return false; } -public: // Create an empty ptr queue set. PtrQueueSet(bool notify_when_complete = false); + ~PtrQueueSet(); // Because of init-order concerns, we can't pass these as constructor // arguments. - void initialize(Monitor* cbl_mon, Mutex* fl_lock, + void initialize(Monitor* cbl_mon, + Mutex* fl_lock, int process_completed_threshold, int max_completed_queue, - PtrQueueSet *fl_owner = NULL) { - _max_completed_queue = max_completed_queue; - _process_completed_threshold = process_completed_threshold; - _completed_queue_padding = 0; - assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?"); - _cbl_mon = cbl_mon; - _fl_lock = fl_lock; - _fl_owner = (fl_owner != NULL) ? fl_owner : this; - } + PtrQueueSet *fl_owner = NULL); - // Return an empty oop array of size _sz (required to be non-zero). +public: + + // Return an empty array of size _sz (required to be non-zero). void** allocate_buffer(); // Return an empty buffer to the free list. The "buf" argument is diff --git a/hotspot/src/share/vm/gc/g1/satbQueue.cpp b/hotspot/src/share/vm/gc/g1/satbMarkQueue.cpp similarity index 84% rename from hotspot/src/share/vm/gc/g1/satbQueue.cpp rename to hotspot/src/share/vm/gc/g1/satbMarkQueue.cpp index 2c9d1adb57b..c10dcff1301 100644 --- a/hotspot/src/share/vm/gc/g1/satbQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/satbMarkQueue.cpp @@ -24,7 +24,7 @@ #include "precompiled.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/satbQueue.hpp" +#include "gc/g1/satbMarkQueue.hpp" #include "gc/shared/collectedHeap.hpp" #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" @@ -33,7 +33,16 @@ #include "runtime/thread.hpp" #include "runtime/vmThread.hpp" -void ObjPtrQueue::flush() { +SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent) : + // SATB queues are only active during marking cycles. We create + // them with their active field set to false. If a thread is + // created during a cycle and its SATB queue needs to be activated + // before the thread starts running, we'll need to set its active + // field to true. This is done in JavaThread::initialize_queues(). + PtrQueue(qset, permanent, false /* active */) +{ } + +void SATBMarkQueue::flush() { // Filter now to possibly save work later. If filtering empties the // buffer then flush_impl can deallocate the buffer. filter(); @@ -79,7 +88,7 @@ inline bool requires_marking(const void* entry, G1CollectedHeap* heap) { assert(heap->is_in_reserved(entry), "Non-heap pointer in SATB buffer: " PTR_FORMAT, p2i(entry)); - HeapRegion* region = heap->heap_region_containing_raw(entry); + HeapRegion* region = heap->heap_region_containing(entry); assert(region != NULL, "No region for " PTR_FORMAT, p2i(entry)); if (entry >= region->next_top_at_mark_start()) { return false; @@ -96,10 +105,9 @@ inline bool requires_marking(const void* entry, G1CollectedHeap* heap) { // they require marking and are not already marked. Retained entries // are compacted toward the top of the buffer. -void ObjPtrQueue::filter() { +void SATBMarkQueue::filter() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); void** buf = _buf; - size_t sz = _sz; if (buf == NULL) { // nothing to do @@ -107,43 +115,37 @@ void ObjPtrQueue::filter() { } // Used for sanity checking at the end of the loop. - debug_only(size_t entries = 0; size_t retained = 0;) + DEBUG_ONLY(size_t entries = 0; size_t retained = 0;) - size_t i = sz; - size_t new_index = sz; + assert(_index <= _sz, "invariant"); + void** limit = &buf[byte_index_to_index(_index)]; + void** src = &buf[byte_index_to_index(_sz)]; + void** dst = src; - while (i > _index) { - assert(i > 0, "we should have at least one more entry to process"); - i -= oopSize; - debug_only(entries += 1;) - void** p = &buf[byte_index_to_index((int) i)]; - void* entry = *p; + while (limit < src) { + DEBUG_ONLY(entries += 1;) + --src; + void* entry = *src; // NULL the entry so that unused parts of the buffer contain NULLs // at the end. If we are going to retain it we will copy it to its // final place. If we have retained all entries we have visited so // far, we'll just end up copying it to the same place. - *p = NULL; + *src = NULL; if (requires_marking(entry, g1h) && !g1h->isMarkedNext((oop)entry)) { - assert(new_index > 0, "we should not have already filled up the buffer"); - new_index -= oopSize; - assert(new_index >= i, - "new_index should never be below i, as we always compact 'up'"); - void** new_p = &buf[byte_index_to_index((int) new_index)]; - assert(new_p >= p, "the destination location should never be below " - "the source as we always compact 'up'"); - assert(*new_p == NULL, - "we should have already cleared the destination location"); - *new_p = entry; - debug_only(retained += 1;) + --dst; + assert(*dst == NULL, "filtering destination should be clear"); + *dst = entry; + DEBUG_ONLY(retained += 1;); } } + size_t new_index = pointer_delta(dst, buf, 1); #ifdef ASSERT - size_t entries_calc = (sz - _index) / oopSize; + size_t entries_calc = (_sz - _index) / sizeof(void*); assert(entries == entries_calc, "the number of entries we counted " "should match the number of entries we calculated"); - size_t retained_calc = (sz - new_index) / oopSize; + size_t retained_calc = (_sz - new_index) / sizeof(void*); assert(retained == retained_calc, "the number of retained entries we counted " "should match the number of retained entries we calculated"); #endif // ASSERT @@ -157,7 +159,7 @@ void ObjPtrQueue::filter() { // allow the mutator to carry on executing using the same buffer // instead of replacing it. -bool ObjPtrQueue::should_enqueue_buffer() { +bool SATBMarkQueue::should_enqueue_buffer() { assert(_lock == NULL || _lock->owned_by_self(), "we should have taken the lock before calling this"); @@ -170,23 +172,20 @@ bool ObjPtrQueue::should_enqueue_buffer() { filter(); - size_t sz = _sz; - size_t all_entries = sz / oopSize; - size_t retained_entries = (sz - _index) / oopSize; - size_t perc = retained_entries * 100 / all_entries; - bool should_enqueue = perc > (size_t) G1SATBBufferEnqueueingThresholdPercent; + size_t percent_used = ((_sz - _index) * 100) / _sz; + bool should_enqueue = percent_used > G1SATBBufferEnqueueingThresholdPercent; return should_enqueue; } -void ObjPtrQueue::apply_closure_and_empty(SATBBufferClosure* cl) { +void SATBMarkQueue::apply_closure_and_empty(SATBBufferClosure* cl) { assert(SafepointSynchronize::is_at_safepoint(), "SATB queues must only be processed at safepoints"); if (_buf != NULL) { assert(_index % sizeof(void*) == 0, "invariant"); assert(_sz % sizeof(void*) == 0, "invariant"); assert(_index <= _sz, "invariant"); - cl->do_buffer(_buf + byte_index_to_index((int)_index), - byte_index_to_index((int)(_sz - _index))); + cl->do_buffer(_buf + byte_index_to_index(_index), + byte_index_to_index(_sz - _index)); _index = _sz; } } @@ -194,25 +193,21 @@ void ObjPtrQueue::apply_closure_and_empty(SATBBufferClosure* cl) { #ifndef PRODUCT // Helpful for debugging -void ObjPtrQueue::print(const char* name) { +void SATBMarkQueue::print(const char* name) { print(name, _buf, _index, _sz); } -void ObjPtrQueue::print(const char* name, - void** buf, size_t index, size_t sz) { +void SATBMarkQueue::print(const char* name, + void** buf, size_t index, size_t sz) { gclog_or_tty->print_cr(" SATB BUFFER [%s] buf: " PTR_FORMAT " " "index: " SIZE_FORMAT " sz: " SIZE_FORMAT, name, p2i(buf), index, sz); } #endif // PRODUCT -#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away -#pragma warning( disable:4355 ) // 'this' : used in base member initializer list -#endif // _MSC_VER - SATBMarkQueueSet::SATBMarkQueueSet() : PtrQueueSet(), - _shared_satb_queue(this, true /*perm*/) { } + _shared_satb_queue(this, true /* permanent */) { } void SATBMarkQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, int process_completed_threshold, @@ -299,7 +294,7 @@ bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) // Filtering can result in non-full completed buffers; see // should_enqueue_buffer. assert(_sz % sizeof(void*) == 0, "invariant"); - size_t limit = ObjPtrQueue::byte_index_to_index((int)_sz); + size_t limit = SATBMarkQueue::byte_index_to_index(_sz); for (size_t i = 0; i < limit; ++i) { if (buf[i] != NULL) { // Found the end of the block of NULLs; process the remainder. @@ -331,7 +326,7 @@ void SATBMarkQueueSet::print_all(const char* msg) { while (nd != NULL) { void** buf = BufferNode::make_buffer_from_node(nd); jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Enqueued: %d", i); - ObjPtrQueue::print(buffer, buf, 0, _sz); + SATBMarkQueue::print(buffer, buf, 0, _sz); nd = nd->next(); i += 1; } diff --git a/hotspot/src/share/vm/gc/g1/satbQueue.hpp b/hotspot/src/share/vm/gc/g1/satbMarkQueue.hpp similarity index 82% rename from hotspot/src/share/vm/gc/g1/satbQueue.hpp rename to hotspot/src/share/vm/gc/g1/satbMarkQueue.hpp index 2e916a7c9a8..0ca3b45c2ff 100644 --- a/hotspot/src/share/vm/gc/g1/satbQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/satbMarkQueue.hpp @@ -22,8 +22,8 @@ * */ -#ifndef SHARE_VM_GC_G1_SATBQUEUE_HPP -#define SHARE_VM_GC_G1_SATBQUEUE_HPP +#ifndef SHARE_VM_GC_G1_SATBMARKQUEUE_HPP +#define SHARE_VM_GC_G1_SATBMARKQUEUE_HPP #include "gc/g1/ptrQueue.hpp" #include "memory/allocation.hpp" @@ -41,8 +41,8 @@ public: virtual void do_buffer(void** buffer, size_t size) = 0; }; -// A ptrQueue whose elements are "oops", pointers to object heads. -class ObjPtrQueue: public PtrQueue { +// A PtrQueue whose elements are (possibly stale) pointers to object heads. +class SATBMarkQueue: public PtrQueue { friend class SATBMarkQueueSet; private: @@ -50,13 +50,7 @@ private: void filter(); public: - ObjPtrQueue(PtrQueueSet* qset, bool perm = false) : - // SATB queues are only active during marking cycles. We create - // them with their active field set to false. If a thread is - // created during a cycle and its SATB queue needs to be activated - // before the thread starts running, we'll need to set its active - // field to true. This is done in JavaThread::initialize_queues(). - PtrQueue(qset, perm, false /* active */) { } + SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent = false); // Process queue entries and free resources. void flush(); @@ -77,7 +71,7 @@ public: }; class SATBMarkQueueSet: public PtrQueueSet { - ObjPtrQueue _shared_satb_queue; + SATBMarkQueue _shared_satb_queue; #ifdef ASSERT void dump_active_states(bool expected_active); @@ -114,10 +108,10 @@ public: void print_all(const char* msg); #endif // PRODUCT - ObjPtrQueue* shared_satb_queue() { return &_shared_satb_queue; } + SATBMarkQueue* shared_satb_queue() { return &_shared_satb_queue; } // If a marking is being abandoned, reset any unprocessed log buffers. void abandon_partial_marking(); }; -#endif // SHARE_VM_GC_G1_SATBQUEUE_HPP +#endif // SHARE_VM_GC_G1_SATBMARKQUEUE_HPP diff --git a/hotspot/src/share/vm/gc/g1/sparsePRT.cpp b/hotspot/src/share/vm/gc/g1/sparsePRT.cpp index 7c82d5204d9..f282ae922d0 100644 --- a/hotspot/src/share/vm/gc/g1/sparsePRT.cpp +++ b/hotspot/src/share/vm/gc/g1/sparsePRT.cpp @@ -32,8 +32,6 @@ #include "runtime/atomic.inline.hpp" #include "runtime/mutexLocker.hpp" -#define SPARSE_PRT_VERBOSE 0 - void SparsePRTEntry::init(RegionIdx_t region_ind) { _region_ind = region_ind; _next_index = NullEntry; @@ -121,11 +119,6 @@ bool RSHashTable::add_card(RegionIdx_t region_ind, CardIdx_t card_index) { "Postcondition of call above."); SparsePRTEntry::AddCardResult res = e->add_card(card_index); if (res == SparsePRTEntry::added) _occupied_cards++; -#if SPARSE_PRT_VERBOSE - gclog_or_tty->print_cr(" after add_card[%d]: valid-cards = %d.", - pointer_delta(e, _entries, SparsePRTEntry::size()), - e->num_valid_cards()); -#endif assert(e->num_valid_cards() > 0, "Postcondition"); return res != SparsePRTEntry::overflow; } @@ -387,10 +380,6 @@ size_t SparsePRT::mem_size() const { } bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) { -#if SPARSE_PRT_VERBOSE - gclog_or_tty->print_cr(" Adding card %d from region %d to region %u sparse.", - card_index, region_id, _hr->hrm_index()); -#endif if (_next->occupied_entries() * 2 > _next->capacity()) { expand(); } @@ -438,18 +427,9 @@ void SparsePRT::cleanup() { void SparsePRT::expand() { RSHashTable* last = _next; _next = new RSHashTable(last->capacity() * 2); - -#if SPARSE_PRT_VERBOSE - gclog_or_tty->print_cr(" Expanded sparse table for %u to %d.", - _hr->hrm_index(), _next->capacity()); -#endif for (size_t i = 0; i < last->capacity(); i++) { SparsePRTEntry* e = last->entry((int)i); if (e->valid_entry()) { -#if SPARSE_PRT_VERBOSE - gclog_or_tty->print_cr(" During expansion, transferred entry for %d.", - e->r_ind()); -#endif _next->add_entry(e); } } diff --git a/hotspot/src/share/vm/gc/g1/workerDataArray.cpp b/hotspot/src/share/vm/gc/g1/workerDataArray.cpp new file mode 100644 index 00000000000..420fc9c6ef8 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, 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 "gc/g1/workerDataArray.inline.hpp" + +#ifndef PRODUCT +void WorkerDataArray_test() { + const uint length = 3; + const char* title = "Test array"; + const bool print_sum = false; + const int log_level = 3; + const uint indent_level = 2; + + WorkerDataArray array(length, title, print_sum, log_level, indent_level); + assert(strncmp(array.title(), title, strlen(title)) == 0 , "Expected titles to match"); + assert(array.should_print_sum() == print_sum, "Expected should_print_sum to match print_sum"); + assert(array.log_level() == log_level, "Expected log levels to match"); + assert(array.indentation() == indent_level, "Expected indentation to match"); + + const size_t expected[length] = {5, 3, 7}; + for (uint i = 0; i < length; i++) { + array.set(i, expected[i]); + } + for (uint i = 0; i < length; i++) { + assert(array.get(i) == expected[i], "Expected elements to match"); + } + + assert(array.sum(length) == (5 + 3 + 7), "Expected sums to match"); + assert(array.minimum(length) == 3, "Expected mininum to match"); + assert(array.maximum(length) == 7, "Expected maximum to match"); + assert(array.diff(length) == (7 - 3), "Expected diffs to match"); + assert(array.average(length) == 5, "Expected averages to match"); + + for (uint i = 0; i < length; i++) { + array.add(i, 1); + } + for (uint i = 0; i < length; i++) { + assert(array.get(i) == expected[i] + 1, "Expected add to increment values"); + } +} +#endif diff --git a/hotspot/src/share/vm/gc/g1/workerDataArray.hpp b/hotspot/src/share/vm/gc/g1/workerDataArray.hpp new file mode 100644 index 00000000000..c96c4f9e65d --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.hpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015, 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 "memory/allocation.hpp" +#include "utilities/debug.hpp" + +template +class WorkerDataArray : public CHeapObj { + friend class G1GCParPhasePrinter; + T* _data; + uint _length; + const char* _title; + bool _print_sum; + int _log_level; + uint _indent_level; + bool _enabled; + + WorkerDataArray* _thread_work_items; + + NOT_PRODUCT(inline T uninitialized() const;) + + void set_all(T value); + + public: + WorkerDataArray(uint length, + const char* title, + bool print_sum, + int log_level, + uint indent_level); + + ~WorkerDataArray(); + + void link_thread_work_items(WorkerDataArray* thread_work_items); + void set_thread_work_item(uint worker_i, size_t value); + WorkerDataArray* thread_work_items() const { + return _thread_work_items; + } + + void set(uint worker_i, T value); + T get(uint worker_i) const; + + void add(uint worker_i, T value); + + double average(uint active_threads) const; + T sum(uint active_threads) const; + T minimum(uint active_threads) const; + T maximum(uint active_threads) const; + T diff(uint active_threads) const; + + uint indentation() const { + return _indent_level; + } + + const char* title() const { + return _title; + } + + bool should_print_sum() const { + return _print_sum; + } + + int log_level() const { + return _log_level; + } + + void clear(); + void set_enabled(bool enabled) { + _enabled = enabled; + } + + void reset() PRODUCT_RETURN; + void verify(uint active_threads) const PRODUCT_RETURN; +}; diff --git a/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp b/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp new file mode 100644 index 00000000000..a228dc2309f --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2015, 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 "gc/g1/workerDataArray.hpp" +#include "memory/allocation.inline.hpp" + +template +WorkerDataArray::WorkerDataArray(uint length, + const char* title, + bool print_sum, + int log_level, + uint indent_level) : + _title(title), + _length(0), + _print_sum(print_sum), + _log_level(log_level), + _indent_level(indent_level), + _thread_work_items(NULL), + _enabled(true) { + assert(length > 0, "Must have some workers to store data for"); + _length = length; + _data = NEW_C_HEAP_ARRAY(T, _length, mtGC); + reset(); +} + +template +void WorkerDataArray::set(uint worker_i, T value) { + assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length); + assert(_data[worker_i] == uninitialized(), "Overwriting data for worker %d in %s", worker_i, _title); + _data[worker_i] = value; +} + +template +T WorkerDataArray::get(uint worker_i) const { + assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length); + assert(_data[worker_i] != uninitialized(), "No data added for worker %d", worker_i); + return _data[worker_i]; +} + +template +WorkerDataArray::~WorkerDataArray() { + FREE_C_HEAP_ARRAY(T, _data); +} + +template +void WorkerDataArray::link_thread_work_items(WorkerDataArray* thread_work_items) { + _thread_work_items = thread_work_items; +} + +template +void WorkerDataArray::set_thread_work_item(uint worker_i, size_t value) { + assert(_thread_work_items != NULL, "No sub count"); + _thread_work_items->set(worker_i, value); +} + +template +void WorkerDataArray::add(uint worker_i, T value) { + assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length); + assert(_data[worker_i] != uninitialized(), "No data to add to for worker %d", worker_i); + _data[worker_i] += value; +} + +template +double WorkerDataArray::average(uint active_threads) const { + return sum(active_threads) / (double) active_threads; +} + +template +T WorkerDataArray::sum(uint active_threads) const { + T s = get(0); + for (uint i = 1; i < active_threads; ++i) { + s += get(i); + } + return s; +} + +template +T WorkerDataArray::minimum(uint active_threads) const { + T min = get(0); + for (uint i = 1; i < active_threads; ++i) { + min = MIN2(min, get(i)); + } + return min; +} + +template +T WorkerDataArray::maximum(uint active_threads) const { + T max = get(0); + for (uint i = 1; i < active_threads; ++i) { + max = MAX2(max, get(i)); + } + return max; +} + +template +T WorkerDataArray::diff(uint active_threads) const { + return maximum(active_threads) - minimum(active_threads); +} + +template +void WorkerDataArray::clear() { + set_all(0); +} + +template +void WorkerDataArray::set_all(T value) { + for (uint i = 0; i < _length; i++) { + _data[i] = value; + } +} + +#ifndef PRODUCT +template +void WorkerDataArray::reset() { + set_all(uninitialized()); + if (_thread_work_items != NULL) { + _thread_work_items->reset(); + } +} + +template +void WorkerDataArray::verify(uint active_threads) const { + if (!_enabled) { + return; + } + + assert(active_threads <= _length, "Wrong number of active threads"); + for (uint i = 0; i < active_threads; i++) { + assert(_data[i] != uninitialized(), + "Invalid data for worker %u in '%s'", i, _title); + } + if (_thread_work_items != NULL) { + _thread_work_items->verify(active_threads); + } +} + +template <> +inline size_t WorkerDataArray::uninitialized() const { + return (size_t)-1; +} + +template <> +inline double WorkerDataArray::uninitialized() const { + return -1.0; +} +#endif diff --git a/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp b/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp index 9293a84cf48..1047e0bbc7f 100644 --- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp +++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp @@ -200,7 +200,7 @@ void InstanceMirrorKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* // by calling follow_class_loader explicitly. For non-anonymous classes // the call to follow_class_loader is made when the class loader itself // is handled. - if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) { + if (klass->is_instance_klass() && InstanceKlass::cast(klass)->is_anonymous()) { cm->follow_class_loader(klass->class_loader_data()); } else { cm->follow_klass(klass); diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp index 09f37ef8fc1..0adf7ae4202 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp @@ -347,7 +347,7 @@ public: HeapWord* _partial_obj_addr; region_sz_t _partial_obj_size; region_sz_t volatile _dc_and_los; - bool _blocks_filled; + bool volatile _blocks_filled; #ifdef ASSERT size_t _blocks_filled_count; // Number of block table fills. @@ -498,7 +498,9 @@ ParallelCompactData::RegionData::destination_count() const inline bool ParallelCompactData::RegionData::blocks_filled() const { - return _blocks_filled; + bool result = _blocks_filled; + OrderAccess::acquire(); + return result; } #ifdef ASSERT @@ -512,6 +514,7 @@ ParallelCompactData::RegionData::blocks_filled_count() const inline void ParallelCompactData::RegionData::set_blocks_filled() { + OrderAccess::release(); _blocks_filled = true; // Debug builds count the number of times the table was filled. DEBUG_ONLY(Atomic::inc_ptr(&_blocks_filled_count)); diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index 29f3aeb65a0..fc4181ef307 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp @@ -383,7 +383,7 @@ void DefNewGeneration::compute_new_size() { size_t old_size = gch->old_gen()->capacity(); size_t new_size_before = _virtual_space.committed_size(); - size_t min_new_size = spec()->init_size(); + size_t min_new_size = initial_size(); size_t max_new_size = reserved().byte_size(); assert(min_new_size <= new_size_before && new_size_before <= max_new_size, diff --git a/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp b/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp index f9ec569dbca..03b9e3daae1 100644 --- a/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp +++ b/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp @@ -66,13 +66,6 @@ class TenuredGeneration: public CardGeneration { const char* name() const { return "tenured generation"; } const char* short_name() const { return "Tenured"; } - // Does a "full" (forced) collection invoked on this generation collect - // the young generation as well? Note that this is a hack to allow the - // collection of the young gen first if the flag is set. - virtual bool full_collects_young_generation() const { - return !ScavengeBeforeFullGC; - } - size_t unsafe_max_alloc_nogc() const; size_t contiguous_available() const; diff --git a/hotspot/src/share/vm/gc/shared/cardGeneration.cpp b/hotspot/src/share/vm/gc/shared/cardGeneration.cpp index f85e798de4e..1eff9c9fa3a 100644 --- a/hotspot/src/share/vm/gc/shared/cardGeneration.cpp +++ b/hotspot/src/share/vm/gc/shared/cardGeneration.cpp @@ -208,8 +208,7 @@ void CardGeneration::compute_new_size() { const double min_tmp = used_after_gc / maximum_used_percentage; size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx)); // Don't shrink less than the initial generation size - minimum_desired_capacity = MAX2(minimum_desired_capacity, - spec()->init_size()); + minimum_desired_capacity = MAX2(minimum_desired_capacity, initial_size()); assert(used_after_gc <= minimum_desired_capacity, "sanity check"); if (PrintGC && Verbose) { @@ -262,8 +261,7 @@ void CardGeneration::compute_new_size() { const double minimum_used_percentage = 1.0 - maximum_free_percentage; const double max_tmp = used_after_gc / minimum_used_percentage; size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); - maximum_desired_capacity = MAX2(maximum_desired_capacity, - spec()->init_size()); + maximum_desired_capacity = MAX2(maximum_desired_capacity, initial_size()); if (PrintGC && Verbose) { gclog_or_tty->print_cr(" " " maximum_free_percentage: %6.2f" @@ -299,20 +297,20 @@ void CardGeneration::compute_new_size() { } if (PrintGC && Verbose) { gclog_or_tty->print_cr(" " - " shrinking:" - " initSize: %.1fK" - " maximum_desired_capacity: %.1fK", - spec()->init_size() / (double) K, - maximum_desired_capacity / (double) K); + " shrinking:" + " initSize: %.1fK" + " maximum_desired_capacity: %.1fK", + initial_size() / (double) K, + maximum_desired_capacity / (double) K); gclog_or_tty->print_cr(" " - " shrink_bytes: %.1fK" - " current_shrink_factor: " SIZE_FORMAT - " new shrink factor: " SIZE_FORMAT - " _min_heap_delta_bytes: %.1fK", - shrink_bytes / (double) K, - current_shrink_factor, - _shrink_factor, - _min_heap_delta_bytes / (double) K); + " shrink_bytes: %.1fK" + " current_shrink_factor: " SIZE_FORMAT + " new shrink factor: " SIZE_FORMAT + " _min_heap_delta_bytes: %.1fK", + shrink_bytes / (double) K, + current_shrink_factor, + _shrink_factor, + _min_heap_delta_bytes / (double) K); } } } diff --git a/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp b/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp index f9b86321fe1..11146d8750e 100644 --- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp +++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp @@ -66,6 +66,7 @@ void ConcurrentGCThread::wait_for_universe_init() { } void ConcurrentGCThread::terminate() { + assert(_should_terminate, "Should only be called on terminate request."); // Signal that it is terminated { MutexLockerEx mu(Terminator_lock, diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index c4ab3fe7862..5724808b142 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -460,10 +460,9 @@ void GenCollectedHeap::do_collection(bool full, bool prepared_for_verification = false; bool collected_old = false; - bool old_collects_young = complete && - _old_gen->full_collects_young_generation(); - if (!old_collects_young && - _young_gen->should_collect(full, size, is_tlab)) { + bool old_collects_young = complete && !ScavengeBeforeFullGC; + + if (!old_collects_young && _young_gen->should_collect(full, size, is_tlab)) { if (run_verification && VerifyGCLevel <= 0 && VerifyBeforeGC) { prepare_for_verify(); prepared_for_verification = true; @@ -1107,10 +1106,6 @@ void GenCollectedHeap::prepare_for_compaction() { _young_gen->prepare_for_compaction(&cp); } -GCStats* GenCollectedHeap::gc_stats(Generation* gen) const { - return gen->gc_stats(); -} - void GenCollectedHeap::verify(bool silent, VerifyOption option /* ignored */) { if (!silent) { gclog_or_tty->print("%s", _old_gen->name()); diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp index e7df6cd57dd..954bc8ad281 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp @@ -126,8 +126,6 @@ public: WorkGang* workers() const { return _workers; } - GCStats* gc_stats(Generation* generation) const; - // Returns JNI_OK on success virtual jint initialize(); diff --git a/hotspot/src/share/vm/gc/shared/generation.cpp b/hotspot/src/share/vm/gc/shared/generation.cpp index c18734ec77d..8663f5449cd 100644 --- a/hotspot/src/share/vm/gc/shared/generation.cpp +++ b/hotspot/src/share/vm/gc/shared/generation.cpp @@ -58,12 +58,12 @@ Generation::Generation(ReservedSpace rs, size_t initial_size) : (HeapWord*)_virtual_space.high_boundary()); } -GenerationSpec* Generation::spec() { +size_t Generation::initial_size() { GenCollectedHeap* gch = GenCollectedHeap::heap(); if (gch->is_young_gen(this)) { - return gch->gen_policy()->young_gen_spec(); + return gch->gen_policy()->young_gen_spec()->init_size(); } - return gch->gen_policy()->old_gen_spec(); + return gch->gen_policy()->old_gen_spec()->init_size(); } size_t Generation::max_capacity() const { diff --git a/hotspot/src/share/vm/gc/shared/generation.hpp b/hotspot/src/share/vm/gc/shared/generation.hpp index 8a21dbb2977..7e35485510b 100644 --- a/hotspot/src/share/vm/gc/shared/generation.hpp +++ b/hotspot/src/share/vm/gc/shared/generation.hpp @@ -141,14 +141,14 @@ class Generation: public CHeapObj { } virtual Generation::Name kind() { return Generation::Other; } - GenerationSpec* spec(); // This properly belongs in the collector, but for now this // will do. virtual bool refs_discovery_is_atomic() const { return true; } virtual bool refs_discovery_is_mt() const { return false; } - // Space enquiries (results in bytes) + // Space inquiries (results in bytes) + size_t initial_size(); virtual size_t capacity() const = 0; // The maximum number of object bytes the // generation can currently hold. virtual size_t used() const = 0; // The number of used bytes in the gen. @@ -309,10 +309,6 @@ class Generation: public CHeapObj { // do nothing. virtual void par_oop_since_save_marks_iterate_done(int thread_num) {} - // This generation will collect all younger generations - // during a full collection. - virtual bool full_collects_young_generation() const { return false; } - // This generation does in-place marking, meaning that mark words // are mutated during the marking phase and presumably reinitialized // to a canonical value after the GC. This is currently used by the @@ -403,7 +399,7 @@ class Generation: public CHeapObj { // that was most recently collected. This allows the generation to // decide what statistics are valid to collect. For example, the // generation can decide to gather the amount of promoted data if - // the collection of the younger generations has completed. + // the collection of the young generation has completed. GCStats* gc_stats() const { return _gc_stats; } virtual void update_gc_stats(Generation* current_generation, bool full) {} diff --git a/hotspot/src/share/vm/gc/shared/generationSpec.cpp b/hotspot/src/share/vm/gc/shared/generationSpec.cpp index a243d674c58..31de065cb0a 100644 --- a/hotspot/src/share/vm/gc/shared/generationSpec.cpp +++ b/hotspot/src/share/vm/gc/shared/generationSpec.cpp @@ -58,9 +58,7 @@ Generation* GenerationSpec::init(ReservedSpace rs, CardTableRS* remset) { // else registers with an existing CMSCollector ConcurrentMarkSweepGeneration* g = NULL; - g = new ConcurrentMarkSweepGeneration(rs, - init_size(), remset, UseCMSAdaptiveFreeLists, - (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice); + g = new ConcurrentMarkSweepGeneration(rs, init_size(), remset); g->initialize_performance_counters(); diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp index ba2cd40f35b..684b64e2b21 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp @@ -373,7 +373,8 @@ void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, // so that the References are not considered active. while (obj != next_d) { obj = next_d; - assert(obj->is_instanceRef(), "should be reference object"); + assert(obj->is_instance(), "should be an instance object"); + assert(InstanceKlass::cast(obj->klass())->is_reference_instance_klass(), "should be reference object"); next_d = java_lang_ref_Reference::discovered(obj); if (TraceReferenceGC && PrintGCDetails) { gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT, diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 4acda1233fa..e43d42d2d6d 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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,7 +194,7 @@ class AbstractInterpreter: AllStatic { bool is_bottom_frame); // Runtime support - static bool is_not_reached( methodHandle method, int bci); + static bool is_not_reached(const methodHandle& method, int bci); // Safepoint support static void notice_safepoints() { ShouldNotReachHere(); } // stops the thread when reaching a safepoint static void ignore_safepoints() { ShouldNotReachHere(); } // ignores safepoints diff --git a/hotspot/src/share/vm/interpreter/bytecode.hpp b/hotspot/src/share/vm/interpreter/bytecode.hpp index 0708816ff51..f3fc9ea9d6a 100644 --- a/hotspot/src/share/vm/interpreter/bytecode.hpp +++ b/hotspot/src/share/vm/interpreter/bytecode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -179,7 +179,7 @@ class Bytecode_member_ref: public Bytecode { protected: const methodHandle _method; // method containing the bytecode - Bytecode_member_ref(methodHandle method, int bci) : Bytecode(method(), method()->bcp_from(bci)), _method(method) {} + Bytecode_member_ref(const methodHandle& method, int bci) : Bytecode(method(), method()->bcp_from(bci)), _method(method) {} methodHandle method() const { return _method; } ConstantPool* constants() const { return _method->constants(); } @@ -201,10 +201,10 @@ class Bytecode_member_ref: public Bytecode { class Bytecode_invoke: public Bytecode_member_ref { protected: // Constructor that skips verification - Bytecode_invoke(methodHandle method, int bci, bool unused) : Bytecode_member_ref(method, bci) {} + Bytecode_invoke(const methodHandle& method, int bci, bool unused) : Bytecode_member_ref(method, bci) {} public: - Bytecode_invoke(methodHandle method, int bci) : Bytecode_member_ref(method, bci) { verify(); } + Bytecode_invoke(const methodHandle& method, int bci) : Bytecode_member_ref(method, bci) { verify(); } void verify() const; // Attributes @@ -232,10 +232,10 @@ class Bytecode_invoke: public Bytecode_member_ref { private: // Helper to skip verification. Used is_valid() to check if the result is really an invoke - inline friend Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci); + inline friend Bytecode_invoke Bytecode_invoke_check(const methodHandle& method, int bci); }; -inline Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci) { +inline Bytecode_invoke Bytecode_invoke_check(const methodHandle& method, int bci) { return Bytecode_invoke(method, bci, false); } @@ -243,7 +243,7 @@ inline Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci) { // Abstraction for all field accesses (put/get field/static) class Bytecode_field: public Bytecode_member_ref { public: - Bytecode_field(methodHandle method, int bci) : Bytecode_member_ref(method, bci) { verify(); } + Bytecode_field(const methodHandle& method, int bci) : Bytecode_member_ref(method, bci) { verify(); } // Testers bool is_getfield() const { return java_code() == Bytecodes::_getfield; } @@ -316,7 +316,7 @@ class Bytecode_loadconstant: public Bytecode { int raw_index() const; public: - Bytecode_loadconstant(methodHandle method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method) { verify(); } + Bytecode_loadconstant(const methodHandle& method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method) { verify(); } void verify() const { assert(_method.not_null(), "must supply method"); diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index a9252c2bfa7..841d3012690 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -2148,11 +2148,8 @@ run: if (!constants->tag_at(index).is_unresolved_klass()) { // Make sure klass is initialized and doesn't have a finalizer Klass* entry = constants->slot_at(index).get_klass(); - assert(entry->is_klass(), "Should be resolved klass"); - Klass* k_entry = (Klass*) entry; - assert(k_entry->oop_is_instance(), "Should be InstanceKlass"); - InstanceKlass* ik = (InstanceKlass*) k_entry; - if ( ik->is_initialized() && ik->can_be_fastpath_allocated() ) { + InstanceKlass* ik = InstanceKlass::cast(entry); + if (ik->is_initialized() && ik->can_be_fastpath_allocated() ) { size_t obj_size = ik->size_helper(); oop result = NULL; // If the TLAB isn't pre-zeroed then we'll have to do it @@ -2193,7 +2190,7 @@ run: result->set_mark(markOopDesc::prototype()); } result->set_klass_gap(0); - result->set_klass(k_entry); + result->set_klass(ik); // Must prevent reordering of stores for object initialization // with stores that publish the new object. OrderAccess::storestore(); @@ -2609,9 +2606,9 @@ run: - klass: {other class} but using InstanceKlass::cast(STACK_OBJECT(-parms)->klass()) causes in assertion failure - because rcvr->klass()->oop_is_instance() == 0 + because rcvr->klass()->is_instance_klass() == 0 However it seems to have a vtable in the right location. Huh? - + Because vtables have the same offset for ArrayKlass and InstanceKlass. */ callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()]; // Profile virtual call. diff --git a/hotspot/src/share/vm/interpreter/bytecodeStream.hpp b/hotspot/src/share/vm/interpreter/bytecodeStream.hpp index 1f657b98bc2..65a0aa4631a 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeStream.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodeStream.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ class BaseBytecodeStream: StackObj { bool _is_raw; // false in 'cooked' BytecodeStream // Construction - BaseBytecodeStream(methodHandle method) : _method(method) { + BaseBytecodeStream(const methodHandle& method) : _method(method) { set_interval(0, _method->code_size()); _is_raw = false; } @@ -118,7 +118,7 @@ class BaseBytecodeStream: StackObj { class RawBytecodeStream: public BaseBytecodeStream { public: // Construction - RawBytecodeStream(methodHandle method) : BaseBytecodeStream(method) { + RawBytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) { _is_raw = true; } @@ -169,7 +169,7 @@ class BytecodeStream: public BaseBytecodeStream { public: // Construction - BytecodeStream(methodHandle method) : BaseBytecodeStream(method) { } + BytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) { } // Iteration Bytecodes::Code next() { diff --git a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp index a0d52b0d196..a1ae0eee4a6 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp @@ -84,7 +84,7 @@ class BytecodePrinter: public BytecodeClosure { // This method is called while executing the raw bytecodes, so none of // the adjustments that BytecodeStream performs applies. - void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { + void trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { ResourceMark rm; if (_current_method != method()) { // Note 1: This code will not work as expected with true MT/MP. @@ -126,7 +126,7 @@ class BytecodePrinter: public BytecodeClosure { // Used for Method*::print_codes(). The input bcp comes from // BytecodeStream, which will skip wide bytecodes. - void trace(methodHandle method, address bcp, outputStream* st) { + void trace(const methodHandle& method, address bcp, outputStream* st) { _current_method = method(); ResourceMark rm; Bytecodes::Code code = Bytecodes::code_at(method(), bcp); @@ -166,7 +166,7 @@ BytecodeClosure* BytecodeTracer::std_closure() { } -void BytecodeTracer::trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { +void BytecodeTracer::trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) { ttyLocker ttyl; // 5065316: keep the following output coherent // The ttyLocker also prevents races between two threads @@ -185,7 +185,7 @@ void BytecodeTracer::trace(methodHandle method, address bcp, uintptr_t tos, uint } } -void BytecodeTracer::trace(methodHandle method, address bcp, outputStream* st) { +void BytecodeTracer::trace(const methodHandle& method, address bcp, outputStream* st) { ttyLocker ttyl; // 5065316: keep the following output coherent _closure->trace(method, bcp, st); } @@ -390,7 +390,6 @@ void BytecodePrinter::print_field_or_method(int orig_i, int i, outputStream* st) } -PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL void BytecodePrinter::print_attributes(int bci, outputStream* st) { // Show attributes of pre-rewritten codes Bytecodes::Code code = Bytecodes::java_code(raw_code()); @@ -512,15 +511,11 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) { } st->print(" %d " INT32_FORMAT " " INT32_FORMAT " ", default_dest, lo, hi); - int first = true; - for (int ll = lo; ll <= hi; ll++, first = false) { + const char *comma = ""; + for (int ll = lo; ll <= hi; ll++) { int idx = ll - lo; - const char *format = first ? " %d:" INT32_FORMAT " (delta: %d)" : - ", %d:" INT32_FORMAT " (delta: %d)"; -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL - st->print(format, ll, dest[idx], dest[idx]-bci); -PRAGMA_DIAG_POP + st->print("%s %d:" INT32_FORMAT " (delta: %d)", comma, ll, dest[idx], dest[idx]-bci); + comma = ","; } st->cr(); } @@ -536,14 +531,10 @@ PRAGMA_DIAG_POP dest[i] = bci + get_int(); }; st->print(" %d %d ", default_dest, len); - bool first = true; - for (int ll = 0; ll < len; ll++, first = false) { - const char *format = first ? " " INT32_FORMAT ":" INT32_FORMAT : - ", " INT32_FORMAT ":" INT32_FORMAT ; -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL - st->print(format, key[ll], dest[ll]); -PRAGMA_DIAG_POP + const char *comma = ""; + for (int ll = 0; ll < len; ll++) { + st->print("%s " INT32_FORMAT ":" INT32_FORMAT, comma, key[ll], dest[ll]); + comma = ","; } st->cr(); } diff --git a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp index 9e5837139a2..06d2a1d8899 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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,8 @@ class BytecodeTracer: AllStatic { static BytecodeClosure* closure() { return _closure; } static void set_closure(BytecodeClosure* closure) { _closure = closure; } - static void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st = tty); - static void trace(methodHandle method, address bcp, outputStream* st = tty); + static void trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st = tty); + static void trace(const methodHandle& method, address bcp, outputStream* st = tty); }; @@ -55,8 +55,8 @@ class BytecodeTracer: AllStatic { class BytecodeClosure { public: - virtual void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) = 0; - virtual void trace(methodHandle method, address bcp, outputStream* st) = 0; + virtual void trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) = 0; + virtual void trace(const methodHandle& method, address bcp, outputStream* st) = 0; }; #endif // SHARE_VM_INTERPRETER_BYTECODETRACER_HPP diff --git a/hotspot/src/share/vm/interpreter/interpreter.cpp b/hotspot/src/share/vm/interpreter/interpreter.cpp index eada76cb3bb..1f4e08bcd43 100644 --- a/hotspot/src/share/vm/interpreter/interpreter.cpp +++ b/hotspot/src/share/vm/interpreter/interpreter.cpp @@ -320,7 +320,7 @@ void AbstractInterpreter::set_entry_for_kind(AbstractInterpreter::MethodKind kin // Return true if the interpreter can prove that the given bytecode has // not yet been executed (in Java semantics, not in actual operation). -bool AbstractInterpreter::is_not_reached(methodHandle method, int bci) { +bool AbstractInterpreter::is_not_reached(const methodHandle& method, int bci) { Bytecodes::Code code = method()->code_at(bci); if (!Bytecodes::must_rewrite(code)) { diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index ebc4832283c..60991b96ca8 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -480,7 +480,7 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea } while (should_repeat == true); #if INCLUDE_JVMCI - if (UseJVMCICompiler && h_method->method_data() != NULL) { + if (EnableJVMCI && h_method->method_data() != NULL) { ResourceMark rm(thread); ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci, NULL); if (pdata != NULL && pdata->is_BitData()) { @@ -1192,7 +1192,7 @@ address SignatureHandlerLibrary::set_handler(CodeBuffer* buffer) { return handler; } -void SignatureHandlerLibrary::add(methodHandle method) { +void SignatureHandlerLibrary::add(const methodHandle& method) { if (method->signature_handler() == NULL) { // use slow signature handler if we can't do better int handler_index = -1; diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index bdbde617cba..297102c4f1a 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -218,7 +218,7 @@ class SignatureHandlerLibrary: public AllStatic { static void pd_set_handler(address handler); public: - static void add(methodHandle method); + static void add(const methodHandle& method); static void add(uint64_t fingerprint, address handler); }; diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 7988d6f5f87..173ec0ec667 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -237,7 +237,7 @@ void CallInfo::print() { //------------------------------------------------------------------------------------------------------------------------ // Implementation of LinkInfo -LinkInfo::LinkInfo(constantPoolHandle pool, int index, TRAPS) { +LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) { // resolve klass Klass* result = pool->klass_ref_at(index, CHECK); _resolved_klass = KlassHandle(THREAD, result); @@ -302,17 +302,19 @@ methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info, // Ignore overpasses so statics can be found during resolution Method* result = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); - if (klass->oop_is_array()) { + if (klass->is_array_klass()) { // Only consider klass and super klass for arrays return methodHandle(THREAD, result); } + InstanceKlass* ik = InstanceKlass::cast(klass()); + // JDK 8, JVMS 5.4.3.4: Interface method resolution should // ignore static and non-public methods of java.lang.Object, // like clone, finalize, registerNatives. if (in_imethod_resolve && result != NULL && - klass->is_interface() && + ik->is_interface() && (result->is_static() || !result->is_public()) && result->method_holder() == SystemDictionary::Object_klass()) { result = NULL; @@ -321,11 +323,11 @@ methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info, // Before considering default methods, check for an overpass in the // current class if a method has not been found. if (result == NULL) { - result = InstanceKlass::cast(klass())->find_method(name, signature); + result = ik->find_method(name, signature); } if (result == NULL) { - Array* default_methods = InstanceKlass::cast(klass())->default_methods(); + Array* default_methods = ik->default_methods(); if (default_methods != NULL) { result = InstanceKlass::find_method(default_methods, name, signature); } @@ -353,7 +355,7 @@ methodHandle LinkResolver::lookup_instance_method_in_klasses(KlassHandle klass, result = super_klass->uncached_lookup_method(name, signature, Klass::find_overpass); } - if (klass->oop_is_array()) { + if (klass->is_array_klass()) { // Only consider klass and super klass for arrays return methodHandle(THREAD, result); } @@ -374,21 +376,21 @@ int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, int vtable_index = Method::invalid_vtable_index; Symbol* name = resolved_method->name(); Symbol* signature = resolved_method->signature(); + InstanceKlass* ik = InstanceKlass::cast(klass()); // First check in default method array - if (!resolved_method->is_abstract() && - (InstanceKlass::cast(klass())->default_methods() != NULL)) { - int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), + if (!resolved_method->is_abstract() && ik->default_methods() != NULL) { + int index = InstanceKlass::find_method_index(ik->default_methods(), name, signature, Klass::find_overpass, Klass::find_static, Klass::find_private); if (index >= 0 ) { - vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index); + vtable_index = ik->default_vtable_indices()->at(index); } } if (vtable_index == Method::invalid_vtable_index) { // get vtable_index for miranda methods ResourceMark rm; - klassVtable *vt = InstanceKlass::cast(klass())->vtable(); + klassVtable *vt = ik->vtable(); vtable_index = vt->index_of_miranda(name, signature); } return vtable_index; @@ -529,7 +531,7 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass, // to be false (so we'll short-circuit out of these tests). if (sel_method->name() == vmSymbols::clone_name() && sel_klass() == SystemDictionary::Object_klass() && - resolved_klass->oop_is_array()) { + resolved_klass->is_array_klass()) { // We need to change "protected" to "public". assert(flags.is_protected(), "clone not protected?"); jint new_flags = flags.as_int(); @@ -559,7 +561,7 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass, } methodHandle LinkResolver::resolve_method_statically(Bytecodes::Code code, - constantPoolHandle pool, int index, TRAPS) { + const constantPoolHandle& pool, int index, TRAPS) { // This method is used only // (1) in C2 from InlineTree::ok_to_inline (via ciMethod::check_call), // and @@ -682,7 +684,7 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, // 2. lookup method in resolved klass and its super klasses methodHandle resolved_method = lookup_method_in_klasses(link_info, true, false, CHECK_NULL); - if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // not found in the class hierarchy + if (resolved_method.is_null() && !resolved_klass->is_array_klass()) { // not found in the class hierarchy // 3. lookup method in all the interfaces implemented by the resolved klass resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL); @@ -742,7 +744,7 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, // JDK8: also look for static methods methodHandle resolved_method = lookup_method_in_klasses(link_info, false, true, CHECK_NULL); - if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { + if (resolved_method.is_null() && !resolved_klass->is_array_klass()) { // lookup method in all the super-interfaces resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL); } @@ -816,7 +818,7 @@ void LinkResolver::check_field_accessability(KlassHandle ref_klass, } } -void LinkResolver::resolve_field_access(fieldDescriptor& fd, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) { +void LinkResolver::resolve_field_access(fieldDescriptor& fd, const constantPoolHandle& pool, int index, Bytecodes::Code byte, TRAPS) { LinkInfo link_info(pool, index, CHECK); resolve_field(fd, link_info, byte, true, CHECK); } @@ -1442,7 +1444,7 @@ methodHandle LinkResolver::resolve_special_call_or_null(const LinkInfo& link_inf //------------------------------------------------------------------------------------------------------------------------ // ConstantPool entries -void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) { +void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, Bytecodes::Code byte, TRAPS) { switch (byte) { case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break; case Bytecodes::_invokespecial : resolve_invokespecial (result, pool, index, CHECK); break; @@ -1454,20 +1456,20 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHan return; } -void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { +void LinkResolver::resolve_invokestatic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { LinkInfo link_info(pool, index, CHECK); resolve_static_call(result, link_info, /*initialize_class*/true, CHECK); } -void LinkResolver::resolve_invokespecial(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { +void LinkResolver::resolve_invokespecial(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { LinkInfo link_info(pool, index, CHECK); resolve_special_call(result, link_info, CHECK); } void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, - constantPoolHandle pool, int index, + const constantPoolHandle& pool, int index, TRAPS) { LinkInfo link_info(pool, index, CHECK); @@ -1476,14 +1478,14 @@ void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, } -void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) { +void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS) { LinkInfo link_info(pool, index, CHECK); KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass()); resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK); } -void LinkResolver::resolve_invokehandle(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { +void LinkResolver::resolve_invokehandle(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { // This guy is reached from InterpreterRuntime::resolve_invokehandle. LinkInfo link_info(pool, index, CHECK); if (TraceMethodHandles) { @@ -1528,7 +1530,7 @@ static void wrap_invokedynamic_exception(TRAPS) { } } -void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { +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); KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder()); diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index 77cd1632549..198eefbe2c0 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -136,7 +136,7 @@ class LinkInfo : public StackObj { KlassHandle _current_klass; // class that owns the constant pool bool _check_access; public: - LinkInfo(constantPoolHandle pool, int index, TRAPS); + LinkInfo(const constantPoolHandle& pool, int index, TRAPS); // Condensed information from other call sites within the vm. LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature, KlassHandle current_klass, bool check_access = true) : @@ -226,17 +226,17 @@ class LinkResolver: AllStatic { // runtime resolving from constant pool static void resolve_invokestatic (CallInfo& result, - constantPoolHandle pool, int index, TRAPS); + const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokespecial (CallInfo& result, - constantPoolHandle pool, int index, TRAPS); + const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokevirtual (CallInfo& result, Handle recv, - constantPoolHandle pool, int index, TRAPS); + const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokeinterface(CallInfo& result, Handle recv, - constantPoolHandle pool, int index, TRAPS); + const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokedynamic (CallInfo& result, - constantPoolHandle pool, int index, TRAPS); + const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokehandle (CallInfo& result, - constantPoolHandle pool, int index, TRAPS); + const constantPoolHandle& pool, int index, TRAPS); public: // constant pool resolving static void check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS); @@ -244,11 +244,11 @@ class LinkResolver: AllStatic { // static resolving calls (will not run any Java code); // used only from Bytecode_invoke::static_target static methodHandle resolve_method_statically(Bytecodes::Code code, - constantPoolHandle pool, + const constantPoolHandle& pool, int index, TRAPS); static void resolve_field_access(fieldDescriptor& result, - constantPoolHandle pool, + const constantPoolHandle& pool, int index, Bytecodes::Code byte, TRAPS); static void resolve_field(fieldDescriptor& result, const LinkInfo& link_info, Bytecodes::Code access_kind, @@ -293,7 +293,7 @@ class LinkResolver: AllStatic { // runtime resolving from constant pool static void resolve_invoke(CallInfo& result, Handle recv, - constantPoolHandle pool, int index, + const constantPoolHandle& pool, int index, Bytecodes::Code byte, TRAPS); private: static void trace_method_resolution(const char* prefix, KlassHandle klass, diff --git a/hotspot/src/share/vm/interpreter/oopMapCache.cpp b/hotspot/src/share/vm/interpreter/oopMapCache.cpp index 2233f1b0f3f..7dcf024532e 100644 --- a/hotspot/src/share/vm/interpreter/oopMapCache.cpp +++ b/hotspot/src/share/vm/interpreter/oopMapCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -426,7 +426,7 @@ void InterpreterOopMap::resource_copy(OopMapCacheEntry* from) { } } -inline unsigned int OopMapCache::hash_value_for(methodHandle method, int bci) const { +inline unsigned int OopMapCache::hash_value_for(const methodHandle& method, int bci) const { // We use method->code_size() rather than method->identity_hash() below since // the mark may not be present if a pointer to the method is already reversed. return ((unsigned int) bci) @@ -477,7 +477,7 @@ void OopMapCache::flush_obsolete_entries() { } } -void OopMapCache::lookup(methodHandle method, +void OopMapCache::lookup(const methodHandle& method, int bci, InterpreterOopMap* entry_for) const { MutexLocker x(&_mut); @@ -558,7 +558,7 @@ void OopMapCache::lookup(methodHandle method, return; } -void OopMapCache::compute_one_oop_map(methodHandle method, int bci, InterpreterOopMap* entry) { +void OopMapCache::compute_one_oop_map(const methodHandle& method, int bci, InterpreterOopMap* entry) { // Due to the invariants above it's tricky to allocate a temporary OopMapCacheEntry on the stack OopMapCacheEntry* tmp = NEW_C_HEAP_ARRAY(OopMapCacheEntry, 1, mtClass); tmp->initialize(); diff --git a/hotspot/src/share/vm/interpreter/oopMapCache.hpp b/hotspot/src/share/vm/interpreter/oopMapCache.hpp index 19bf0044925..cb9367e150f 100644 --- a/hotspot/src/share/vm/interpreter/oopMapCache.hpp +++ b/hotspot/src/share/vm/interpreter/oopMapCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -116,7 +116,7 @@ class InterpreterOopMap: ResourceObj { void set_expression_stack_size(int sz) { _expression_stack_size = sz; } // Lookup - bool match(methodHandle method, int bci) const { return _method == method() && _bci == bci; } + bool match(const methodHandle& method, int bci) const { return _method == method() && _bci == bci; } bool is_empty() const; // Initialization @@ -151,7 +151,7 @@ class OopMapCache : public CHeapObj { OopMapCacheEntry* _array; - unsigned int hash_value_for(methodHandle method, int bci) const; + unsigned int hash_value_for(const methodHandle& method, int bci) const; OopMapCacheEntry* entry_at(int i) const; mutable Mutex _mut; @@ -167,10 +167,10 @@ class OopMapCache : public CHeapObj { // Returns the oopMap for (method, bci) in parameter "entry". // Returns false if an oop map was not found. - void lookup(methodHandle method, int bci, InterpreterOopMap* entry) const; + void lookup(const methodHandle& method, int bci, InterpreterOopMap* entry) const; // Compute an oop map without updating the cache or grabbing any locks (for debugging) - static void compute_one_oop_map(methodHandle method, int bci, InterpreterOopMap* entry); + static void compute_one_oop_map(const methodHandle& method, int bci, InterpreterOopMap* entry); // Returns total no. of bytes allocated as part of OopMapCache's static long memory_usage() PRODUCT_RETURN0; diff --git a/hotspot/src/share/vm/interpreter/rewriter.cpp b/hotspot/src/share/vm/interpreter/rewriter.cpp index 01122e7ecf7..e5e51af1e2e 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.cpp +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp @@ -509,7 +509,7 @@ void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) { // (That's all, folks.) } -Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array* methods, TRAPS) +Rewriter::Rewriter(instanceKlassHandle klass, const constantPoolHandle& cpool, Array* methods, TRAPS) : _klass(klass), _pool(cpool), _methods(methods) diff --git a/hotspot/src/share/vm/interpreter/rewriter.hpp b/hotspot/src/share/vm/interpreter/rewriter.hpp index aa4b7cd5228..de25b101e84 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.hpp +++ b/hotspot/src/share/vm/interpreter/rewriter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -185,7 +185,7 @@ class Rewriter: public StackObj { } // All the work goes in here: - Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array* methods, TRAPS); + Rewriter(instanceKlassHandle klass, const constantPoolHandle& cpool, Array* methods, TRAPS); void compute_index_maps(); void make_constant_pool_cache(TRAPS); diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp index 8d75f5e1ed4..73beefc6766 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp @@ -562,7 +562,7 @@ void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState t if (StopInterpreterAt > 0) stop_interpreter_at(); __ verify_FPU(1, t->tos_in()); #endif // !PRODUCT - int step; + int step = 0; if (!t->does_dispatch()) { step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode()); if (tos_out == ilgl) tos_out = t->tos_out(); diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp index bbf5e992f58..3a46b2281fd 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp @@ -142,42 +142,38 @@ OopMap* CodeInstaller::create_oop_map(oop debug_info) { return map; } -static void record_metadata_reference(oop obj, jlong prim, jboolean compressed, OopRecorder* oop_recorder) { +Metadata* CodeInstaller::record_metadata_reference(Handle& constant) { + oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant); if (obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) { Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj)); - if (compressed) { - assert(Klass::decode_klass((narrowKlass) prim) == klass, "%s @ " INTPTR_FORMAT " != " PTR64_FORMAT, klass->name()->as_C_string(), p2i(klass), prim); - } else { - assert((Klass*) prim == klass, "%s @ " INTPTR_FORMAT " != " PTR64_FORMAT, klass->name()->as_C_string(), p2i(klass), prim); - } - int index = oop_recorder->find_index(klass); - TRACE_jvmci_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string()); + assert(!HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected compressed klass pointer %s @ " INTPTR_FORMAT, klass->name()->as_C_string(), p2i(klass)); + int index = _oop_recorder->find_index(klass); + TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string()); + return klass; } else if (obj->is_a(HotSpotResolvedJavaMethodImpl::klass())) { Method* method = (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(obj); - assert(!compressed, "unexpected compressed method pointer %s @ " INTPTR_FORMAT " = " PTR64_FORMAT, method->name()->as_C_string(), p2i(method), prim); - int index = oop_recorder->find_index(method); - TRACE_jvmci_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string()); + assert(!HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected compressed method pointer %s @ " INTPTR_FORMAT, method->name()->as_C_string(), p2i(method)); + int index = _oop_recorder->find_index(method); + TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), method->name()->as_C_string()); + return method; } else { - assert(java_lang_String::is_instance(obj), - "unexpected metadata reference (%s) for constant " JLONG_FORMAT " (" PTR64_FORMAT ")", obj->klass()->name()->as_C_string(), prim, prim); + fatal("unexpected metadata reference for constant of type %s", obj->klass()->name()->as_C_string()); + return NULL; } } -// Records any Metadata values embedded in a Constant (e.g., the value returned by HotSpotResolvedObjectTypeImpl.klass()). -static void record_metadata_in_constant(oop constant, OopRecorder* oop_recorder) { - if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) { - oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant); - jlong prim = HotSpotMetaspaceConstantImpl::primitive(constant); - assert(obj != NULL, "must have an object"); - assert(prim != 0, "must have a primitive value"); +#ifdef _LP64 +narrowKlass CodeInstaller::record_narrow_metadata_reference(Handle& constant) { + oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant); + assert(HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected uncompressed pointer"); + assert(obj->is_a(HotSpotResolvedObjectTypeImpl::klass()), "unexpected compressed pointer of type %s", obj->klass()->name()->as_C_string()); - record_metadata_reference(obj, prim, false, oop_recorder); - } -} - -static void record_metadata_in_patch(Handle& constant, OopRecorder* oop_recorder) { - record_metadata_reference(HotSpotMetaspaceConstantImpl::metaspaceObject(constant), HotSpotMetaspaceConstantImpl::primitive(constant), HotSpotMetaspaceConstantImpl::compressed(constant), oop_recorder); + Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj)); + int index = _oop_recorder->find_index(klass); + TRACE_jvmci_3("narrowKlass[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string()); + return Klass::encode_klass(klass); } +#endif Location::Type CodeInstaller::get_oop_type(oop value) { oop lirKind = Value::lirKind(value); @@ -253,7 +249,6 @@ ScopeValue* CodeInstaller::get_scope_value(oop value, BasicType type, GrowableAr } return value; } else if (value->is_a(JavaConstant::klass())) { - record_metadata_in_constant(value, _oop_recorder); if (value->is_a(PrimitiveConstant::klass())) { if (value->is_a(RawConstant::klass())) { jlong prim = PrimitiveConstant::primitive(value); @@ -379,14 +374,15 @@ void CodeInstaller::initialize_dependencies(oop compiled_code, OopRecorder* reco } } } - objArrayHandle methods = HotSpotCompiledCode::methods(compiled_code); - if (!methods.is_null()) { - int length = methods->length(); - for (int i = 0; i < length; ++i) { - Handle method_handle = methods->obj_at(i); - methodHandle method = getMethodFromHotSpotMethod(method_handle()); - - _dependencies->assert_evol_method(method()); + if (JvmtiExport::can_hotswap_or_post_breakpoint()) { + objArrayHandle methods = HotSpotCompiledCode::methods(compiled_code); + if (!methods.is_null()) { + int length = methods->length(); + for (int i = 0; i < length; ++i) { + Handle method_handle = methods->obj_at(i); + methodHandle method = getMethodFromHotSpotMethod(method_handle()); + _dependencies->assert_evol_method(method()); + } } } } @@ -543,7 +539,7 @@ void CodeInstaller::initialize_fields(oop target, oop compiled_code) { } int CodeInstaller::estimate_stubs_size() { - // Return size for all stubs. + // Estimate the number of static call stubs that might be emitted. int static_call_stubs = 0; objArrayOop sites = this->sites(); for (int i = 0; i < sites->length(); i++) { @@ -564,6 +560,7 @@ int CodeInstaller::estimate_stubs_size() { // perform data and call relocation on the CodeBuffer JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer) { + HandleMark hm; objArrayHandle sites = this->sites(); int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo)); @@ -606,14 +603,22 @@ JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer) Handle reference = CompilationResult_DataPatch::reference(patch); assert(reference->is_a(CompilationResult_ConstantReference::klass()), "patch in data section must be a ConstantReference"); Handle constant = CompilationResult_ConstantReference::constant(reference); + address dest = _constants->start() + CompilationResult_Site::pcOffset(patch); if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) { - record_metadata_in_patch(constant, _oop_recorder); + if (HotSpotMetaspaceConstantImpl::compressed(constant)) { +#ifdef _LP64 + *((narrowKlass*) dest) = record_narrow_metadata_reference(constant); +#else + fatal("unexpected compressed Klass* in 32-bit mode"); +#endif + } else { + *((Metadata**) dest) = record_metadata_reference(constant); + } } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) { Handle obj = HotSpotObjectConstantImpl::object(constant); jobject value = JNIHandles::make_local(obj()); int oop_index = _oop_recorder->find_index(value); - address dest = _constants->start() + CompilationResult_Site::pcOffset(patch); if (HotSpotObjectConstantImpl::compressed(constant)) { #ifdef _LP64 _constants->relocate(dest, oop_Relocation::spec(oop_index), relocInfo::narrow_oop_in_const); @@ -960,7 +965,7 @@ void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) if (constant->is_a(HotSpotObjectConstantImpl::klass())) { pd_patch_OopConstant(pc_offset, constant); } else if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) { - record_metadata_in_patch(constant, _oop_recorder); + pd_patch_MetaspaceConstant(pc_offset, constant); } else if (constant->is_a(HotSpotSentinelConstant::klass())) { fatal("sentinel constant unsupported"); } else { @@ -1014,6 +1019,7 @@ void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) { case POLL_RETURN_FAR: pd_relocate_poll(pc, id); break; + case CARD_TABLE_SHIFT: case CARD_TABLE_ADDRESS: case HEAP_TOP_ADDRESS: case HEAP_END_ADDRESS: diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp index b0d3016b645..2ee2cbd742c 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp @@ -107,10 +107,11 @@ private: POLL_FAR = 13, POLL_RETURN_FAR = 14, CARD_TABLE_ADDRESS = 15, - HEAP_TOP_ADDRESS = 16, - HEAP_END_ADDRESS = 17, - NARROW_KLASS_BASE_ADDRESS = 18, - CRC_TABLE_ADDRESS = 19, + CARD_TABLE_SHIFT = 16, + HEAP_TOP_ADDRESS = 17, + HEAP_END_ADDRESS = 18, + NARROW_KLASS_BASE_ADDRESS = 19, + CRC_TABLE_ADDRESS = 20, INVOKE_INVALID = -1 }; @@ -155,8 +156,8 @@ private: jint pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method); void pd_patch_OopConstant(int pc_offset, Handle& constant); + void pd_patch_MetaspaceConstant(int pc_offset, Handle& constant); void pd_patch_DataSectionReference(int pc_offset, int data_offset); - void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst); void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination); void pd_relocate_JavaMethod(oop method, jint pc_offset); void pd_relocate_poll(address pc, jint mark); @@ -170,11 +171,10 @@ private: objArrayOop comments() { return (objArrayOop) JNIHandles::resolve(_comments_handle); } #endif - void record_resolved(oop obj); - oop word_kind() { return (oop) JNIHandles::resolve(_word_kind_handle); } public: + CodeInstaller() : _arena(mtCompiler) {} JVMCIEnv::CodeInstallResult gather_metadata(Handle target, Handle& compiled_code, CodeMetadata& metadata); @@ -191,6 +191,11 @@ protected: ScopeValue* get_scope_value(oop value, BasicType type, GrowableArray* objects, ScopeValue* &second); MonitorValue* get_monitor_value(oop value, GrowableArray* objects); + Metadata* record_metadata_reference(Handle& constant); +#ifdef _LP64 + narrowKlass record_narrow_metadata_reference(Handle& constant); +#endif + // extract the fields of the CompilationResult void initialize_fields(oop target, oop target_method); void initialize_dependencies(oop target_method, OopRecorder* oop_recorder); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp index 7cb959a96b8..7fdf21e60ee 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -57,6 +57,10 @@ void JVMCICompiler::initialize() { } void JVMCICompiler::bootstrap() { + if (Arguments::mode() == Arguments::_int) { + // Nothing to do in -Xint mode + return; + } #ifndef PRODUCT // We turn off CompileTheWorld so that compilation requests are not // ignored during bootstrap or that JVMCI can be compiled by C1/C2. @@ -72,7 +76,7 @@ void JVMCICompiler::bootstrap() { } jlong start = os::javaTimeMillis(); - Array* objectMethods = InstanceKlass::cast(SystemDictionary::Object_klass())->methods(); + Array* objectMethods = SystemDictionary::Object_klass()->methods(); // Initialize compile queue with a selected set of methods. int len = objectMethods->length(); for (int i = 0; i < len; i++) { @@ -125,22 +129,40 @@ void JVMCICompiler::compile_method(methodHandle method, int entry_bci, JVMCIEnv* Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_ABORT); JavaValue method_result(T_OBJECT); - { + JavaCallArguments args; + args.push_long((jlong) (address) method()); + JavaCalls::call_static(&method_result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(), + vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, THREAD); + + if (!HAS_PENDING_EXCEPTION) { + JavaValue result(T_VOID); JavaCallArguments args; - args.push_long((jlong) (address) method()); - JavaCalls::call_static(&method_result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, CHECK_ABORT); + args.push_oop(receiver); + args.push_oop((oop)method_result.get_jobject()); + args.push_int(entry_bci); + args.push_long((jlong) (address) env); + args.push_int(env->task()->compile_id()); + JavaCalls::call_special(&result, receiver->klass(), + vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD); } - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(receiver); - args.push_oop((oop)method_result.get_jobject()); - args.push_int(entry_bci); - args.push_long((jlong) (address) env); - args.push_int(env->task()->compile_id()); - JavaCalls::call_special(&result, receiver->klass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, CHECK_ABORT); + // An uncaught exception was thrown during compilation. Generally these + // should be handled by the Java code in some useful way but if they leak + // through to here report them instead of dying or silently ignoring them. + if (HAS_PENDING_EXCEPTION) { + Handle throwable = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; - _methodsCompiled++; + JVMCIRuntime::call_printStackTrace(throwable, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } + + // Something went wrong so disable compilation at this level + method->set_not_compilable(CompLevel_full_optimization); + } else { + _methodsCompiled++; + } } @@ -149,6 +171,13 @@ void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, ShouldNotReachHere(); } +bool JVMCICompiler::is_trivial(Method* method) { + if (_bootstrapping) { + return false; + } + return JVMCIRuntime::treat_as_trivial(method); +} + // Print compilation timers and statistics void JVMCICompiler::print_timers() { print_compilation_timers(); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp index b4d3a4964bf..0b0a38d5afa 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp @@ -73,6 +73,8 @@ public: void compile_method(methodHandle target, int entry_bci, JVMCIEnv* env); + virtual bool is_trivial(Method* method); + // Print compilation timers and statistics virtual void print_timers(); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index 2430d33a3c8..c0f773e279b 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -60,7 +60,7 @@ #define C2V_END } -oop CompilerToVM::get_jvmci_method(methodHandle method, TRAPS) { +oop CompilerToVM::get_jvmci_method(const methodHandle& method, TRAPS) { if (method() != NULL) { JavaValue result(T_OBJECT); JavaCallArguments args; @@ -84,6 +84,24 @@ oop CompilerToVM::get_jvmci_type(KlassHandle klass, TRAPS) { return NULL; } +void CompilerToVM::invalidate_installed_code(Handle installedCode, TRAPS) { + if (installedCode() == NULL) { + THROW(vmSymbols::java_lang_NullPointerException()); + } + jlong nativeMethod = InstalledCode::address(installedCode); + nmethod* nm = (nmethod*)nativeMethod; + assert(nm == NULL || nm->jvmci_installed_code() == installedCode(), "sanity check"); + if (nm != NULL && nm->is_alive()) { + // The nmethod state machinery maintains the link between the + // HotSpotInstalledCode and nmethod* so as long as the nmethod appears to be + // alive assume there is work to do and deoptimize the nmethod. + nm->mark_for_deoptimization(); + VM_Deoptimize op; + VMThread::execute(&op); + } + InstalledCode::set_address(installedCode, 0); +} + extern "C" { extern VMStructEntry* gHotSpotVMStructs; extern uint64_t gHotSpotVMStructEntryTypeNameOffset; @@ -538,8 +556,8 @@ C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv *, jobject, jobject if (!method->method_holder()->is_interface()) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Method %s is not held by an interface, this case should be handled in Java code", method->name_and_sig_as_C_string())); } - if (!InstanceKlass::cast(klass)->is_initialized()) { - THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Class %s must be initialized", klass->external_name())); + if (!InstanceKlass::cast(klass)->is_linked()) { + THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Class %s must be linked", klass->external_name())); } return LinkResolver::vtable_index_of_interface_method(klass, method); C2V_END @@ -549,7 +567,7 @@ C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_t Klass* caller_klass = CompilerToVM::asKlass(caller_jvmci_type); Method* method = CompilerToVM::asMethod(jvmci_method); - if (recv_klass->oop_is_array() || (InstanceKlass::cast(recv_klass)->is_linked())) { + if (recv_klass->is_array_klass() || (InstanceKlass::cast(recv_klass)->is_linked())) { Klass* holder_klass = method->method_holder(); Symbol* method_name = method->name(); Symbol* method_signature = method->signature(); @@ -670,8 +688,13 @@ C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject } else { if (!installed_code_handle.is_null()) { assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type"); + CompilerToVM::invalidate_installed_code(installed_code_handle, CHECK_0); InstalledCode::set_address(installed_code_handle, (jlong) cb); - InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1); + if (cb->is_nmethod()) { + InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->as_nmethod_or_null()->verified_entry_point()); + } else { + InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->code_begin()); + } if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) { HotSpotInstalledCode::set_size(installed_code_handle, cb->size()); HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin()); @@ -782,10 +805,19 @@ C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject)) stats->_osr.reset(); C2V_END -C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jlong codeBlob)) +C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jobject installedCode)) ResourceMark rm; HandleMark hm; + if (installedCode == NULL) { + THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "installedCode is null"); + } + + jlong codeBlob = InstalledCode::address(installedCode); + if (codeBlob == 0L) { + return NULL; + } + CodeBlob* cb = (CodeBlob*) (address) codeBlob; if (cb == NULL) { return NULL; @@ -936,15 +968,9 @@ C2V_VMENTRY(void, reprofile, (JNIEnv*, jobject, jobject jvmci_method)) C2V_END -C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject hotspotInstalledCode)) - jlong nativeMethod = InstalledCode::address(hotspotInstalledCode); - nmethod* m = (nmethod*)nativeMethod; - if (m != NULL && !m->is_not_entrant()) { - m->mark_for_deoptimization(); - VM_Deoptimize op; - VMThread::execute(&op); - } - InstalledCode::set_address(hotspotInstalledCode, 0); +C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject installed_code)) + Handle installed_code_handle = JNIHandles::resolve(installed_code); + CompilerToVM::invalidate_installed_code(installed_code_handle, CHECK); C2V_END C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv*, jobject, jlong addr)) @@ -991,7 +1017,8 @@ bool matches(jobjectArray methods, Method* method) { objArrayOop methods_oop = (objArrayOop) JNIHandles::resolve(methods); for (int i = 0; i < methods_oop->length(); i++) { - if (CompilerToVM::asMethod(methods_oop->obj_at(i)) == method) { + oop resolved = methods_oop->obj_at(i); + if (resolved->is_a(HotSpotResolvedJavaMethodImpl::klass()) && CompilerToVM::asMethod(resolved) == method) { return true; } } @@ -1284,11 +1311,29 @@ C2V_VMENTRY(void, flushDebugOutput, (JNIEnv*, jobject)) tty->flush(); C2V_END +C2V_VMENTRY(int, methodDataProfileDataSize, (JNIEnv*, jobject, jlong metaspace_method_data, jint position)) + ResourceMark rm; + MethodData* mdo = CompilerToVM::asMethodData(metaspace_method_data); + ProfileData* profile_data = mdo->data_at(position); + if (mdo->is_valid(profile_data)) { + return profile_data->size_in_bytes(); + } + DataLayout* data = mdo->extra_data_base(); + DataLayout* end = mdo->extra_data_limit(); + for (;; data = mdo->next_extra(data)) { + assert(data < end, "moved past end of extra data"); + profile_data = data->data_in(); + if (mdo->dp_to_di(profile_data->dp()) == position) { + return profile_data->size_in_bytes(); + } + } + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Invalid profile data position %d", position)); +C2V_END + #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) -#define SPECULATION_LOG "Ljdk/vm/ci/meta/SpeculationLog;" #define STRING "Ljava/lang/String;" #define OBJECT "Ljava/lang/Object;" #define CLASS "Ljava/lang/Class;" @@ -1300,8 +1345,10 @@ C2V_END #define HS_RESOLVED_KLASS "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;" #define HS_CONSTANT_POOL "Ljdk/vm/ci/hotspot/HotSpotConstantPool;" #define HS_COMPILED_CODE "Ljdk/vm/ci/hotspot/HotSpotCompiledCode;" +#define HS_CONFIG "Ljdk/vm/ci/hotspot/HotSpotVMConfig;" #define HS_METADATA "Ljdk/vm/ci/hotspot/HotSpotMetaData;" #define HS_STACK_FRAME_REF "Ljdk/vm/ci/hotspot/HotSpotStackFrameReference;" +#define HS_SPECULATION_LOG "Ljdk/vm/ci/hotspot/HotSpotSpeculationLog;" #define METASPACE_METHOD_DATA "J" JNINativeMethod CompilerToVM::methods[] = { @@ -1339,12 +1386,12 @@ JNINativeMethod CompilerToVM::methods[] = { {CC"getResolvedJavaMethod", CC"(Ljava/lang/Object;J)"HS_RESOLVED_METHOD, FN_PTR(getResolvedJavaMethod)}, {CC"getConstantPool", CC"(Ljava/lang/Object;J)"HS_CONSTANT_POOL, FN_PTR(getConstantPool)}, {CC"getResolvedJavaType", CC"(Ljava/lang/Object;JZ)"HS_RESOLVED_KLASS, FN_PTR(getResolvedJavaType)}, - {CC"initializeConfiguration", CC"()J", FN_PTR(initializeConfiguration)}, - {CC"installCode", CC"("TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I", FN_PTR(installCode)}, + {CC"initializeConfiguration", CC"("HS_CONFIG")J", FN_PTR(initializeConfiguration)}, + {CC"installCode", CC"("TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE HS_SPECULATION_LOG")I", FN_PTR(installCode)}, {CC"getMetadata", CC"("TARGET_DESCRIPTION HS_COMPILED_CODE HS_METADATA")I", FN_PTR(getMetadata)}, {CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)}, {CC"resetCompilationStatistics", CC"()V", FN_PTR(resetCompilationStatistics)}, - {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)}, + {CC"disassembleCodeBlob", CC"("INSTALLED_CODE")"STRING, FN_PTR(disassembleCodeBlob)}, {CC"executeInstalledCode", CC"(["OBJECT INSTALLED_CODE")"OBJECT, FN_PTR(executeInstalledCode)}, {CC"getLineNumberTable", CC"("HS_RESOLVED_METHOD")[J", FN_PTR(getLineNumberTable)}, {CC"getLocalVariableTableStart", CC"("HS_RESOLVED_METHOD")J", FN_PTR(getLocalVariableTableStart)}, @@ -1357,11 +1404,12 @@ JNINativeMethod CompilerToVM::methods[] = { {CC"isMature", CC"("METASPACE_METHOD_DATA")Z", FN_PTR(isMature)}, {CC"hasCompiledCodeForOSR", CC"("HS_RESOLVED_METHOD"II)Z", FN_PTR(hasCompiledCodeForOSR)}, {CC"getSymbol", CC"(J)"STRING, FN_PTR(getSymbol)}, - {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF "["HS_RESOLVED_METHOD"I)"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)}, + {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF "["RESOLVED_METHOD"I)"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)}, {CC"materializeVirtualObjects", CC"("HS_STACK_FRAME_REF"Z)V", FN_PTR(materializeVirtualObjects)}, {CC"shouldDebugNonSafepoints", CC"()Z", FN_PTR(shouldDebugNonSafepoints)}, {CC"writeDebugOutput", CC"([BII)V", FN_PTR(writeDebugOutput)}, {CC"flushDebugOutput", CC"()V", FN_PTR(flushDebugOutput)}, + {CC"methodDataProfileDataSize", CC"(JI)I", FN_PTR(methodDataProfileDataSize)}, }; int CompilerToVM::methods_count() { diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp index bf6cc6bb3a0..4acce0bcb93 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -94,9 +94,11 @@ public: return (MethodData*) (address) metaspaceMethodData; } - static oop get_jvmci_method(methodHandle method, TRAPS); + static oop get_jvmci_method(const methodHandle& method, TRAPS); static oop get_jvmci_type(KlassHandle klass, TRAPS); + + static void invalidate_installed_code(Handle installedCode, TRAPS); }; class JavaArgumentUnboxer : public SignatureIterator { diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp index 9758ce6d7bb..348a28601be 100644 --- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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,18 +64,18 @@ JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter // Note: the logic of this method should mirror the logic of // constantPoolOopDesc::verify_constant_pool_resolve. bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass) { - if (accessing_klass->oop_is_objArray()) { + if (accessing_klass->is_objArray_klass()) { accessing_klass = ObjArrayKlass::cast(accessing_klass())->bottom_klass(); } - if (!accessing_klass->oop_is_instance()) { + if (!accessing_klass->is_instance_klass()) { return true; } - if (resolved_klass->oop_is_objArray()) { + if (resolved_klass->is_objArray_klass()) { // Find the element klass, if this is an array. resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass(); } - if (resolved_klass->oop_is_instance()) { + if (resolved_klass->is_instance_klass()) { return Reflection::verify_class_access(accessing_klass(), resolved_klass(), true); } return true; @@ -83,7 +83,7 @@ bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandl // ------------------------------------------------------------------ KlassHandle JVMCIEnv::get_klass_by_name_impl(KlassHandle& accessing_klass, - constantPoolHandle& cpool, + const constantPoolHandle& cpool, Symbol* sym, bool require_local) { JVMCI_EXCEPTION_CONTEXT; @@ -174,7 +174,7 @@ KlassHandle JVMCIEnv::get_klass_by_name(KlassHandle& accessing_klass, // ------------------------------------------------------------------ // Implementation of get_klass_by_index. -KlassHandle JVMCIEnv::get_klass_by_index_impl(constantPoolHandle& cpool, +KlassHandle JVMCIEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, int index, bool& is_accessible, KlassHandle& accessor) { @@ -215,7 +215,7 @@ KlassHandle JVMCIEnv::get_klass_by_index_impl(constantPoolHandle& cpool, // ------------------------------------------------------------------ // Get a klass from the constant pool. -KlassHandle JVMCIEnv::get_klass_by_index(constantPoolHandle& cpool, +KlassHandle JVMCIEnv::get_klass_by_index(const constantPoolHandle& cpool, int index, bool& is_accessible, KlassHandle& accessor) { @@ -312,7 +312,7 @@ methodHandle JVMCIEnv::lookup_method(instanceKlassHandle& h_accessor, // ------------------------------------------------------------------ -methodHandle JVMCIEnv::get_method_by_index_impl(constantPoolHandle& cpool, +methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool, int index, Bytecodes::Code bc, instanceKlassHandle& accessor) { if (bc == Bytecodes::_invokedynamic) { @@ -383,9 +383,9 @@ instanceKlassHandle JVMCIEnv::get_instance_klass_for_declared_method_holder(Klas // For the case of .clone(), the method holder can be an ArrayKlass* // instead of an InstanceKlass*. For that case simply pretend that the // declared holder is Object.clone since that's where the call will bottom out. - if (method_holder->oop_is_instance()) { + if (method_holder->is_instance_klass()) { return instanceKlassHandle(method_holder()); - } else if (method_holder->oop_is_array()) { + } else if (method_holder->is_array_klass()) { return instanceKlassHandle(SystemDictionary::Object_klass()); } else { ShouldNotReachHere(); @@ -395,7 +395,7 @@ instanceKlassHandle JVMCIEnv::get_instance_klass_for_declared_method_holder(Klas // ------------------------------------------------------------------ -methodHandle JVMCIEnv::get_method_by_index(constantPoolHandle& cpool, +methodHandle JVMCIEnv::get_method_by_index(const constantPoolHandle& cpool, int index, Bytecodes::Code bc, instanceKlassHandle& accessor) { ResourceMark rm; @@ -494,12 +494,12 @@ JVMCIEnv::CodeInstallResult JVMCIEnv::register_method( MethodData* mdp = method()->method_data(); if (mdp != NULL) { mdp->inc_decompile_count(); +#ifdef ASSERT if (mdp->decompile_count() > (uint)PerMethodRecompilationCutoff) { - // TODO (chaeubl) enable this in the fastdebug build only once we are more stable ResourceMark m; tty->print_cr("WARN: endless recompilation of %s. Method was set to not compilable.", method()->name_and_sig_as_C_string()); - //ShouldNotReachHere(); } +#endif } // All buffers in the CodeBuffer are allocated in the CodeCache. diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp index db88196310a..f0291efde26 100644 --- a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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,13 +83,13 @@ public: bool require_local); // Constant pool access. - static KlassHandle get_klass_by_index(constantPoolHandle& cpool, + static KlassHandle get_klass_by_index(const constantPoolHandle& cpool, int klass_index, bool& is_accessible, KlassHandle& loading_klass); static void get_field_by_index(instanceKlassHandle& loading_klass, fieldDescriptor& fd, int field_index); - static methodHandle get_method_by_index(constantPoolHandle& cpool, + static methodHandle get_method_by_index(const constantPoolHandle& cpool, int method_index, Bytecodes::Code bc, instanceKlassHandle& loading_klass); @@ -106,16 +106,16 @@ private: // Implementation methods for loading and constant pool access. static KlassHandle get_klass_by_name_impl(KlassHandle& accessing_klass, - constantPoolHandle& cpool, + const constantPoolHandle& cpool, Symbol* klass_name, bool require_local); - static KlassHandle get_klass_by_index_impl(constantPoolHandle& cpool, + static KlassHandle get_klass_by_index_impl(const constantPoolHandle& cpool, int klass_index, bool& is_accessible, KlassHandle& loading_klass); static void get_field_by_index_impl(instanceKlassHandle& loading_klass, fieldDescriptor& fd, int field_index); - static methodHandle get_method_by_index_impl(constantPoolHandle& cpool, + static methodHandle get_method_by_index_impl(const constantPoolHandle& cpool, int method_index, Bytecodes::Code bc, instanceKlassHandle& loading_klass); diff --git a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp index 928fc1d1440..190aaf419f1 100644 --- a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp @@ -71,7 +71,6 @@ void compute_offset(int &dest_offset, Klass* klass, const char* name, const char void JVMCIJavaClasses::compute_offsets() { COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, OOP_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD) - guarantee(InstalledCode::_address_offset == sizeof(oopDesc), "codeBlob must be first field!"); } #define EMPTY0 diff --git a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp index bfd81623cd8..22f6bede118 100644 --- a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp @@ -65,6 +65,7 @@ class JVMCIJavaClasses : AllStatic { end_class \ start_class(InstalledCode) \ long_field(InstalledCode, address) \ + long_field(InstalledCode, entryPoint) \ long_field(InstalledCode, version) \ oop_field(InstalledCode, name, "Ljava/lang/String;") \ end_class \ @@ -215,8 +216,7 @@ class JVMCIJavaClasses : AllStatic { boolean_field(HotSpotObjectConstantImpl, compressed) \ end_class \ start_class(HotSpotMetaspaceConstantImpl) \ - long_field(HotSpotMetaspaceConstantImpl, primitive) \ - oop_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljava/lang/Object;") \ + oop_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljdk/vm/ci/hotspot/MetaspaceWrapperObject;") \ boolean_field(HotSpotMetaspaceConstantImpl, compressed) \ end_class \ start_class(HotSpotSentinelConstant) \ @@ -261,11 +261,11 @@ class JVMCIJavaClasses : AllStatic { end_class \ start_class(StackLockValue) \ oop_field(StackLockValue, owner, "Ljdk/vm/ci/meta/JavaValue;") \ - oop_field(StackLockValue, slot, "Ljdk/vm/ci/code/StackSlotValue;") \ + oop_field(StackLockValue, slot, "Ljdk/vm/ci/meta/AllocatableValue;") \ boolean_field(StackLockValue, eliminated) \ end_class \ - start_class(SpeculationLog) \ - oop_field(SpeculationLog, lastFailed, "Ljava/lang/Object;") \ + start_class(HotSpotSpeculationLog) \ + oop_field(HotSpotSpeculationLog, lastFailed, "Ljava/lang/Object;") \ end_class \ start_class(HotSpotStackFrameReference) \ oop_field(HotSpotStackFrameReference, compilerToVM, "Ljdk/vm/ci/hotspot/CompilerToVM;") \ @@ -292,9 +292,11 @@ class JVMCIJavaClasses : AllStatic { start_class(HotSpotConstantPool) \ long_field(HotSpotConstantPool, metaspaceConstantPool) \ end_class \ + start_class(HotSpotJVMCIRuntime) \ + objArrayOop_field(HotSpotJVMCIRuntime, trivialPrefixes, "[Ljava/lang/String;") \ + end_class \ /* end*/ - #define START_CLASS(name) \ class name : AllStatic { \ private: \ @@ -306,7 +308,7 @@ class name : AllStatic { } \ static void compute_offsets(); \ public: \ - static InstanceKlass* klass() { return SystemDictionary::name##_klass() == NULL ? NULL : InstanceKlass::cast(SystemDictionary::name##_klass()); } + static InstanceKlass* klass() { return SystemDictionary::name##_klass(); } #define END_CLASS }; diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp index d436a265cc7..55632f2acb9 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp @@ -52,6 +52,8 @@ bool JVMCIRuntime::_well_known_classes_initialized = false; const char* JVMCIRuntime::_compiler = NULL; int JVMCIRuntime::_options_count = 0; SystemProperty** JVMCIRuntime::_options = NULL; +int JVMCIRuntime::_trivial_prefixes_count = 0; +char** JVMCIRuntime::_trivial_prefixes = NULL; bool JVMCIRuntime::_shutdown_called = false; static const char* OPTION_PREFIX = "jvmci.option."; @@ -124,7 +126,7 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array(JavaThread* thread, Klass* array_k // (This may have to change if this code changes!) assert(array_klass->is_klass(), "not a class"); oop obj; - if (array_klass->oop_is_typeArray()) { + if (array_klass->is_typeArray_klass()) { BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type(); obj = oopFactory::new_typeArray(elt_type, length, CHECK); } else { @@ -433,12 +435,13 @@ JRT_LEAF(void, JVMCIRuntime::monitorexit(JavaThread* thread, oopDesc* obj, Basic } JRT_END -JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags)) - bool string = mask_bits_are_true(flags, LOG_OBJECT_STRING); - bool addr = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS); - bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE); - if (!string) { - if (!addr && obj->is_oop_or_null(true)) { +JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, bool as_string, bool newline)) + ttyLocker ttyl; + + if (obj == NULL) { + tty->print("NULL"); + } else if (obj->is_oop_or_null(true) && (!as_string || !java_lang_String::is_instance(obj))) { + if (obj->is_oop_or_null(true)) { char buf[O_BUFLEN]; tty->print("%s@" INTPTR_FORMAT, obj->klass()->name()->as_C_string(buf, O_BUFLEN), p2i(obj)); } else { @@ -628,10 +631,10 @@ Handle JVMCIRuntime::callStatic(const char* className, const char* methodName, c static bool jvmci_options_file_exists() { const char* home = Arguments::get_java_home(); - size_t path_len = strlen(home) + strlen("/lib/jvmci/options") + 1; + size_t path_len = strlen(home) + strlen("/lib/jvmci.options") + 1; char path[JVM_MAXPATHLEN]; char sep = os::file_separator()[0]; - jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cjvmci%coptions", home, sep, sep, sep); + jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cjvmci.options", home, sep, sep); struct stat st; return os::stat(path, &st) == 0; } @@ -656,7 +659,8 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) { for (int i = 0; i < _options_count; i++) { SystemProperty* prop = _options[i]; oop name = java_lang_String::create_oop_from_str(prop->key() + OPTION_PREFIX_LEN, CHECK); - oop value = java_lang_String::create_oop_from_str(prop->value(), CHECK); + const char* prop_value = prop->value() != NULL ? prop->value() : ""; + oop value = java_lang_String::create_oop_from_str(prop_value, CHECK); options->obj_at_put(i * 2, name); options->obj_at_put((i * 2) + 1, value); } @@ -682,6 +686,20 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) { Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime", "runtime", "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK); + objArrayOop trivial_prefixes = HotSpotJVMCIRuntime::trivialPrefixes(result); + if (trivial_prefixes != NULL) { + char** prefixes = NEW_C_HEAP_ARRAY(char*, trivial_prefixes->length(), mtCompiler); + for (int i = 0; i < trivial_prefixes->length(); i++) { + oop str = trivial_prefixes->obj_at(i); + if (str == NULL) { + THROW(vmSymbols::java_lang_NullPointerException()); + } else { + prefixes[i] = strdup(java_lang_String::as_utf8_string(str)); + } + } + _trivial_prefixes = prefixes; + _trivial_prefixes_count = trivial_prefixes->length(); + } _HotSpotJVMCIRuntime_initialized = true; _HotSpotJVMCIRuntime_instance = JNIHandles::make_global(result()); } @@ -877,15 +895,27 @@ void JVMCIRuntime::save_compiler(const char* compiler) { _compiler = compiler; } -jint JVMCIRuntime::save_options(SystemProperty* props) { +void JVMCIRuntime::maybe_print_flags(TRAPS) { + if (_options != NULL) { + for (int i = 0; i < _options_count; i++) { + SystemProperty* p = _options[i]; + const char* name = p->key() + OPTION_PREFIX_LEN; + if (strcmp(name, "PrintFlags") == 0 || strcmp(name, "ShowFlags") == 0) { + JVMCIRuntime::initialize_well_known_classes(CHECK); + HandleMark hm; + ResourceMark rm; + JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK); + return; + } + } + } +} + +void JVMCIRuntime::save_options(SystemProperty* props) { int count = 0; SystemProperty* first = NULL; for (SystemProperty* p = props; p != NULL; p = p->next()) { if (strncmp(p->key(), OPTION_PREFIX, OPTION_PREFIX_LEN) == 0) { - if (p->value() == NULL || strlen(p->value()) == 0) { - jio_fprintf(defaultStream::output_stream(), "JVMCI option %s must have non-zero length value\n", p->key()); - return JNI_ERR; - } if (first == NULL) { first = p; } @@ -905,7 +935,6 @@ jint JVMCIRuntime::save_options(SystemProperty* props) { } assert (insert_pos - _options == count, "must be"); } - return JNI_OK; } void JVMCIRuntime::shutdown() { @@ -921,6 +950,20 @@ void JVMCIRuntime::shutdown() { } } +bool JVMCIRuntime::treat_as_trivial(Method* method) { + if (_HotSpotJVMCIRuntime_initialized) { + oop loader = method->method_holder()->class_loader(); + if (loader == NULL) { + for (int i = 0; i < _trivial_prefixes_count; i++) { + if (method->method_holder()->name()->starts_with(_trivial_prefixes[i])) { + return true; + } + } + } + } + return false; +} + void JVMCIRuntime::call_printStackTrace(Handle exception, Thread* thread) { assert(exception->is_a(SystemDictionary::Throwable_klass()), "Throwable instance expected"); JavaValue result(T_VOID); @@ -949,18 +992,18 @@ void JVMCIRuntime::abort_on_pending_exception(Handle exception, const char* mess void JVMCIRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) { struct stat st; - if (os::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file - int file_handle = os::open(path, 0, 0); + if (::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file + int file_handle = ::open(path, os::default_file_open_flags(), 0); if (file_handle != -1) { char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal); int num_read; - num_read = (int) os::read(file_handle, (char*) buffer, st.st_size); + num_read = (int) ::read(file_handle, (char*) buffer, st.st_size); if (num_read == -1) { warning("Error reading file %s due to %s", path, strerror(errno)); } else if (num_read != st.st_size) { warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path); } - os::close(file_handle); + ::close(file_handle); closure->set_filename(path); if (num_read == st.st_size) { buffer[num_read] = '\0'; diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp index df41d67688e..00eae524c15 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp @@ -54,24 +54,6 @@ protected: void set_filename(char* path) {_filename = path; _lineNo = 0;} }; -#define CHECK_ABORT THREAD); \ - if (HAS_PENDING_EXCEPTION) { \ - char buf[256]; \ - jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \ - JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \ - return; \ - } \ - (void)(0 - -#define CHECK_ABORT_(result) THREAD); \ - if (HAS_PENDING_EXCEPTION) { \ - char buf[256]; \ - jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \ - JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \ - return result; \ - } \ - (void)(0 - class JVMCIRuntime: public AllStatic { private: static jobject _HotSpotJVMCIRuntime_instance; @@ -81,6 +63,9 @@ class JVMCIRuntime: public AllStatic { static int _options_count; static SystemProperty** _options; + static int _trivial_prefixes_count; + static char** _trivial_prefixes; + static bool _shutdown_called; /** @@ -108,9 +93,14 @@ class JVMCIRuntime: public AllStatic { * when JVMCI is initialized. * * @param props the head of the system property list - * @return JNI_ERR if a JVMCI option has a zero length value, JNI_OK otherwise */ - static jint save_options(SystemProperty* props); + static void save_options(SystemProperty* props); + + /** + * If either the PrintFlags or ShowFlags JVMCI option is present, + * then JVMCI is initialized to show the help message. + */ + static void maybe_print_flags(TRAPS); static bool is_HotSpotJVMCIRuntime_initialized() { return _HotSpotJVMCIRuntime_initialized; } @@ -150,6 +140,7 @@ class JVMCIRuntime: public AllStatic { return _shutdown_called; } + static bool treat_as_trivial(Method* method); static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure); /** @@ -162,6 +153,24 @@ class JVMCIRuntime: public AllStatic { */ static void call_printStackTrace(Handle exception, Thread* thread); +#define CHECK_ABORT THREAD); \ + if (HAS_PENDING_EXCEPTION) { \ + char buf[256]; \ + jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \ + JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \ + return; \ + } \ + (void)(0 + +#define CHECK_ABORT_(result) THREAD); \ + if (HAS_PENDING_EXCEPTION) { \ + char buf[256]; \ + jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \ + JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \ + return result; \ + } \ + (void)(0 + static BasicType kindToBasicType(jchar ch); // The following routines are all called from compiled JVMCI code @@ -183,13 +192,11 @@ class JVMCIRuntime: public AllStatic { static oopDesc* load_and_clear_exception(JavaThread* thread); static void log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3); static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); - // Note: Must be kept in sync with constants in com.oracle.graal.replacements.Log - enum { - LOG_OBJECT_NEWLINE = 0x01, - LOG_OBJECT_STRING = 0x02, - LOG_OBJECT_ADDRESS = 0x04 - }; - static void log_object(JavaThread* thread, oopDesc* msg, jint flags); + // Print the passed in object, optionally followed by a newline. If + // as_string is true and the object is a java.lang.String then it + // printed as a string, otherwise the type of the object is printed + // followed by its address. + static void log_object(JavaThread* thread, oopDesc* object, bool as_string, bool newline); static void write_barrier_pre(JavaThread* thread, oopDesc* obj); static void write_barrier_post(JavaThread* thread, void* card); static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child); diff --git a/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp b/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp index 931dcaffb9c..58701527f0f 100644 --- a/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp +++ b/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp @@ -47,6 +47,8 @@ do_klass(HotSpotOopMap_klass, jdk_vm_ci_hotspot_HotSpotOopMap, Jvmci) \ do_klass(HotSpotConstantPool_klass, jdk_vm_ci_hotspot_HotSpotConstantPool, Jvmci) \ do_klass(HotSpotJVMCIMetaAccessContext_klass, jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext, Jvmci) \ + do_klass(HotSpotJVMCIRuntime_klass, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime, Jvmci) \ + do_klass(HotSpotSpeculationLog_klass, jdk_vm_ci_hotspot_HotSpotSpeculationLog, Jvmci) \ do_klass(Assumptions_ConcreteMethod_klass, jdk_vm_ci_meta_Assumptions_ConcreteMethod, Jvmci) \ do_klass(Assumptions_NoFinalizableSubclass_klass, jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass, Jvmci) \ do_klass(Assumptions_ConcreteSubtype_klass, jdk_vm_ci_meta_Assumptions_ConcreteSubtype, Jvmci) \ @@ -74,7 +76,6 @@ do_klass(StackSlot_klass, jdk_vm_ci_code_StackSlot, Jvmci) \ do_klass(StackLockValue_klass, jdk_vm_ci_code_StackLockValue, Jvmci) \ do_klass(VirtualObject_klass, jdk_vm_ci_code_VirtualObject, Jvmci) \ - do_klass(SpeculationLog_klass, jdk_vm_ci_meta_SpeculationLog, Jvmci) \ do_klass(JavaConstant_klass, jdk_vm_ci_meta_JavaConstant, Jvmci) \ do_klass(PrimitiveConstant_klass, jdk_vm_ci_meta_PrimitiveConstant, Jvmci) \ do_klass(RawConstant_klass, jdk_vm_ci_meta_RawConstant, Jvmci) \ diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.hpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.hpp index 97ef4466fd9..a58a6ef74c7 100644 --- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.hpp +++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.hpp @@ -70,6 +70,20 @@ declare_constant(CompilerToVM::KLASS_TAG) \ declare_constant(CompilerToVM::SYMBOL_TAG) \ \ + declare_constant(BitData::exception_seen_flag) \ + declare_constant(BitData::null_seen_flag) \ + declare_constant(CounterData::count_off) \ + declare_constant(JumpData::taken_off_set) \ + declare_constant(JumpData::displacement_off_set) \ + declare_constant(ReceiverTypeData::nonprofiled_count_off_set) \ + declare_constant(ReceiverTypeData::receiver_type_row_cell_count) \ + declare_constant(ReceiverTypeData::receiver0_offset) \ + declare_constant(ReceiverTypeData::count0_offset) \ + declare_constant(BranchData::not_taken_off_set) \ + declare_constant(ArrayData::array_len_off_set) \ + declare_constant(ArrayData::array_start_off_set) \ + declare_constant(MultiBranchData::per_case_cell_count) \ + \ declare_constant(CodeInstaller::VERIFIED_ENTRY) \ declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \ declare_constant(CodeInstaller::OSR_ENTRY) \ @@ -84,6 +98,7 @@ declare_constant(CodeInstaller::POLL_RETURN_NEAR) \ declare_constant(CodeInstaller::POLL_FAR) \ declare_constant(CodeInstaller::POLL_RETURN_FAR) \ + declare_constant(CodeInstaller::CARD_TABLE_SHIFT) \ declare_constant(CodeInstaller::CARD_TABLE_ADDRESS) \ declare_constant(CodeInstaller::HEAP_TOP_ADDRESS) \ declare_constant(CodeInstaller::HEAP_END_ADDRESS) \ diff --git a/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp b/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp index eedc51b6e86..5502f2fa603 100644 --- a/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp +++ b/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp @@ -48,6 +48,8 @@ template(jdk_vm_ci_hotspot_HotSpotOopMap, "jdk/vm/ci/hotspot/HotSpotOopMap") \ template(jdk_vm_ci_hotspot_HotSpotConstantPool, "jdk/vm/ci/hotspot/HotSpotConstantPool") \ template(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext, "jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext") \ + template(jdk_vm_ci_hotspot_HotSpotJVMCIRuntime, "jdk/vm/ci/hotspot/HotSpotJVMCIRuntime") \ + template(jdk_vm_ci_hotspot_HotSpotSpeculationLog, "jdk/vm/ci/hotspot/HotSpotSpeculationLog") \ template(jdk_vm_ci_meta_JavaConstant, "jdk/vm/ci/meta/JavaConstant") \ template(jdk_vm_ci_meta_PrimitiveConstant, "jdk/vm/ci/meta/PrimitiveConstant") \ template(jdk_vm_ci_meta_RawConstant, "jdk/vm/ci/meta/RawConstant") \ @@ -61,7 +63,6 @@ template(jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass, "jdk/vm/ci/meta/Assumptions$NoFinalizableSubclass") \ template(jdk_vm_ci_meta_Assumptions_ConcreteMethod, "jdk/vm/ci/meta/Assumptions$ConcreteMethod") \ template(jdk_vm_ci_meta_Assumptions_CallSiteTargetValue, "jdk/vm/ci/meta/Assumptions$CallSiteTargetValue") \ - template(jdk_vm_ci_meta_SpeculationLog, "jdk/vm/ci/meta/SpeculationLog") \ template(jdk_vm_ci_code_Architecture, "jdk/vm/ci/code/Architecture") \ template(jdk_vm_ci_code_TargetDescription, "jdk/vm/ci/code/TargetDescription") \ template(jdk_vm_ci_code_CompilationResult_Call, "jdk/vm/ci/code/CompilationResult$Call") \ diff --git a/hotspot/src/share/vm/libadt/dict.cpp b/hotspot/src/share/vm/libadt/dict.cpp index 9ad56fa657a..9c84ed5825b 100644 --- a/hotspot/src/share/vm/libadt/dict.cpp +++ b/hotspot/src/share/vm/libadt/dict.cpp @@ -126,37 +126,37 @@ void Dict::Clear() { void Dict::doubhash(void) { uint oldsize = _size; _size <<= 1; // Double in size - _bin = (bucket*)_arena->Arealloc( _bin, sizeof(bucket)*oldsize, sizeof(bucket)*_size ); - memset( &_bin[oldsize], 0, oldsize*sizeof(bucket) ); + _bin = (bucket*)_arena->Arealloc(_bin, sizeof(bucket) * oldsize, sizeof(bucket) * _size); + memset(&_bin[oldsize], 0, oldsize * sizeof(bucket)); // Rehash things to spread into new table - for( uint i=0; i < oldsize; i++) { // For complete OLD table do - bucket *b = &_bin[i]; // Handy shortcut for _bin[i] - if( !b->_keyvals ) continue; // Skip empties fast + for (uint i = 0; i < oldsize; i++) { // For complete OLD table do + bucket *b = &_bin[i]; // Handy shortcut for _bin[i] + if (!b->_keyvals) continue; // Skip empties fast - bucket *nb = &_bin[i+oldsize]; // New bucket shortcut - uint j = b->_max; // Trim new bucket to nearest power of 2 - while( j > b->_cnt ) j >>= 1; // above old bucket _cnt - if( !j ) j = 1; // Handle zero-sized buckets - nb->_max = j<<1; + bucket *nb = &_bin[i+oldsize]; // New bucket shortcut + uint j = b->_max; // Trim new bucket to nearest power of 2 + while (j > b->_cnt) { j >>= 1; } // above old bucket _cnt + if (!j) { j = 1; } // Handle zero-sized buckets + nb->_max = j << 1; // Allocate worst case space for key-value pairs - nb->_keyvals = (void**)_arena->Amalloc_4( sizeof(void *)*nb->_max*2 ); + nb->_keyvals = (void**)_arena->Amalloc_4(sizeof(void *) * nb->_max * 2); uint nbcnt = 0; - for( j=0; j_cnt; j++ ) { // Rehash all keys in this bucket - void *key = b->_keyvals[j+j]; - if( (_hash( key ) & (_size-1)) != i ) { // Moving to hi bucket? - nb->_keyvals[nbcnt+nbcnt] = key; - nb->_keyvals[nbcnt+nbcnt+1] = b->_keyvals[j+j+1]; - nb->_cnt = nbcnt = nbcnt+1; - b->_cnt--; // Remove key/value from lo bucket - b->_keyvals[j+j ] = b->_keyvals[b->_cnt+b->_cnt ]; - b->_keyvals[j+j+1] = b->_keyvals[b->_cnt+b->_cnt+1]; - j--; // Hash compacted element also + for (j = 0; j < b->_cnt; ) { // Rehash all keys in this bucket + void *key = b->_keyvals[j + j]; + if ((_hash(key) & (_size-1)) != i) { // Moving to hi bucket? + nb->_keyvals[nbcnt + nbcnt] = key; + nb->_keyvals[nbcnt + nbcnt + 1] = b->_keyvals[j + j + 1]; + nb->_cnt = nbcnt = nbcnt + 1; + b->_cnt--; // Remove key/value from lo bucket + b->_keyvals[j + j] = b->_keyvals[b->_cnt + b->_cnt]; + b->_keyvals[j + j + 1] = b->_keyvals[b->_cnt + b->_cnt + 1]; + // Don't increment j, hash compacted element also. + } else { + j++; // Iterate. } } // End of for all key-value pairs in bucket } // End of for all buckets - - } //------------------------------Dict----------------------------------------- diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp new file mode 100644 index 00000000000..1e9f94bec9d --- /dev/null +++ b/hotspot/src/share/vm/logging/log.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015, 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" + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +#include "logging/log.hpp" +#include "logging/logConfiguration.hpp" +#include "memory/resourceArea.hpp" + +void Test_log_length() { + remove("loglengthoutput.txt"); + + // Write long message to output file + MutexLocker ml(LogConfiguration_lock); + LogConfiguration::parse_log_arguments("loglengthoutput.txt", "logging=develop", + NULL, NULL, NULL); + ResourceMark rm; + outputStream* logstream = LogHandle(logging)::develop_stream(); + logstream->print_cr("01:1234567890-" + "02:1234567890-" + "03:1234567890-" + "04:1234567890-" + "05:1234567890-" + "06:1234567890-" + "07:1234567890-" + "08:1234567890-" + "09:1234567890-" + "10:1234567890-" + "11:1234567890-" + "12:1234567890-" + "13:1234567890-" + "14:1234567890-" + "15:1234567890-" + "16:1234567890-" + "17:1234567890-" + "18:1234567890-" + "19:1234567890-" + "20:1234567890-" + "21:1234567890-" + "22:1234567890-" + "23:1234567890-" + "24:1234567890-" + "25:1234567890-" + "26:1234567890-" + "27:1234567890-" + "28:1234567890-" + "29:1234567890-" + "30:1234567890-" + "31:1234567890-" + "32:1234567890-" + "33:1234567890-" + "34:1234567890-" + "35:1234567890-" + "36:1234567890-" + "37:1234567890-"); + + // Look for end of message in output file + FILE* fp; + fp = fopen("loglengthoutput.txt", "r"); + assert (fp, "File read error"); + char output[600]; + if (fgets(output, 600, fp) != NULL) { + assert(strstr(output, "37:1234567890-"), "logging print size error"); + } + fclose(fp); + remove("loglengthoutput.txt"); +} +#endif // PRODUCT + diff --git a/hotspot/src/share/vm/logging/log.hpp b/hotspot/src/share/vm/logging/log.hpp index 8b1f7c63c2f..2f041afeb78 100644 --- a/hotspot/src/share/vm/logging/log.hpp +++ b/hotspot/src/share/vm/logging/log.hpp @@ -29,6 +29,8 @@ #include "logging/logTagSet.hpp" #include "logging/logTag.hpp" #include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" +#include "runtime/os.hpp" #include "utilities/debug.hpp" #include "utilities/ostream.hpp" @@ -104,9 +106,20 @@ class Log VALUE_OBJ_CLASS_SPEC { static void vwrite(const char* fmt, va_list args) { char buf[LogBufferSize]; size_t prefix_len = LogPrefix::prefix(buf, sizeof(buf)); - int ret = vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, fmt, args); - assert(ret >= 0 && (size_t)ret < sizeof(buf), "Log message too long"); - puts(buf); + // Check that string fits in buffer; resize buffer if necessary + int ret = os::log_vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, fmt, args); + assert(ret >= 0, "Log message buffer issue"); + if ((size_t)ret > sizeof(buf)) { + size_t newbuf_len = prefix_len + ret + 1; + char* newbuf = NEW_C_HEAP_ARRAY(char, newbuf_len, mtLogging); + prefix_len = LogPrefix::prefix(newbuf, newbuf_len); + ret = os::log_vsnprintf(newbuf + prefix_len, newbuf_len - prefix_len, fmt, args); + assert(ret >= 0, "Log message buffer issue"); + puts(newbuf); + FREE_C_HEAP_ARRAY(char, newbuf); + } else { + puts(buf); + } } template diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 0989af3401c..4d5d6caf73d 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -31,7 +31,9 @@ // (The tags 'all', 'disable' and 'help' are special tags that can // not be used in log calls, and should not be listed below.) #define LOG_TAG_LIST \ - LOG_TAG(logging) + LOG_TAG(defaultmethods) \ + LOG_TAG(logging) \ + LOG_TAG(safepoint) #define PREFIX_LOG_TAG(T) (LogTag::T) diff --git a/hotspot/src/share/vm/memory/allocation.cpp b/hotspot/src/share/vm/memory/allocation.cpp index 5f846d3c245..b6287bd5ed1 100644 --- a/hotspot/src/share/vm/memory/allocation.cpp +++ b/hotspot/src/share/vm/memory/allocation.cpp @@ -66,7 +66,7 @@ void MetaspaceObj::print_address_on(outputStream* st) const { } void* ResourceObj::operator new(size_t size, allocation_type type, MEMFLAGS flags) throw() { - address res; + address res = NULL; switch (type) { case C_HEAP: res = (address)AllocateHeap(size, flags, CALLER_PC); @@ -88,8 +88,8 @@ void* ResourceObj::operator new [](size_t size, allocation_type type, MEMFLAGS f void* ResourceObj::operator new(size_t size, const std::nothrow_t& nothrow_constant, allocation_type type, MEMFLAGS flags) throw() { - //should only call this with std::nothrow, use other operator new() otherwise - address res; + // should only call this with std::nothrow, use other operator new() otherwise + address res = NULL; switch (type) { case C_HEAP: res = (address)AllocateHeap(size, flags, CALLER_PC, AllocFailStrategy::RETURN_NULL); diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index c152f6ab525..9113fb02b17 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -168,6 +168,7 @@ void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment _version = _current_version; _alignment = alignment; _obj_alignment = ObjectAlignmentInBytes; + _compact_strings = CompactStrings; _narrow_oop_mode = Universe::narrow_oop_mode(); _narrow_oop_shift = Universe::narrow_oop_shift(); _max_heap_size = MaxHeapSize; @@ -900,6 +901,13 @@ bool FileMapInfo::FileMapHeader::validate() { _obj_alignment, ObjectAlignmentInBytes); return false; } + if (_compact_strings != CompactStrings) { + FileMapInfo::fail_continue("The shared archive file's CompactStrings setting (%s)" + " does not equal the current CompactStrings setting (%s).", + _compact_strings ? "enabled" : "disabled", + CompactStrings ? "enabled" : "disabled"); + return false; + } return true; } diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp index e026c565b1d..8c725cdac02 100644 --- a/hotspot/src/share/vm/memory/filemap.hpp +++ b/hotspot/src/share/vm/memory/filemap.hpp @@ -95,6 +95,7 @@ public: size_t _alignment; // how shared archive should be aligned int _obj_alignment; // value of ObjectAlignmentInBytes int _narrow_oop_shift; // compressed oop encoding shift + bool _compact_strings; // value of CompactStrings uintx _max_heap_size; // java max heap size during dumping Universe::NARROW_OOP_MODE _narrow_oop_mode; // compressed oop encoding mode int _narrow_klass_shift; // save narrow klass base and shift diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp index 6f24c4917af..d120a45218f 100644 --- a/hotspot/src/share/vm/memory/heapInspection.cpp +++ b/hotspot/src/share/vm/memory/heapInspection.cpp @@ -286,7 +286,6 @@ bool KlassInfoHisto::is_selected(const char *col_name) { return true; } -PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL void KlassInfoHisto::print_title(outputStream* st, bool csv_format, bool selected[], int width_table[], const char *name_table[]) { @@ -298,11 +297,10 @@ void KlassInfoHisto::print_title(outputStream* st, bool csv_format, st->print(",ClassName"); } else { st->print("Index Super"); - for (int c=0; cprint(str_fmt(width_table[c]), name_table[c]);} -PRAGMA_DIAG_POP + for (int c = 0; c < KlassSizeStats::_num_columns; c++) { + if (selected[c]) { + st->print("%*s", width_table[c], name_table[c]); + } } st->print(" ClassName"); } @@ -321,7 +319,7 @@ public: void do_cinfo(KlassInfoEntry* cie) { // ignore array classes - if (cie->klass()->oop_is_instance()) { + if (cie->klass()->is_instance_klass()) { _elements->append(cie); } } @@ -348,8 +346,7 @@ void KlassHierarchy::print_class_hierarchy(outputStream* st, bool print_interfac for(int i = 0; i < elements.length(); i++) { KlassInfoEntry* cie = elements.at(i); - const InstanceKlass* k = (InstanceKlass*)cie->klass(); - Klass* super = ((InstanceKlass*)k)->java_super(); + Klass* super = cie->klass()->super(); // Set the index for the class. cie->set_index(i + 1); @@ -544,8 +541,8 @@ void KlassInfoHisto::print_class_stats(outputStream* st, } else { int super_index = -1; // Print the stats for this class. - if (k->oop_is_instance()) { - Klass* super = ((InstanceKlass*)k)->java_super(); + if (k->is_instance_klass()) { + Klass* super = k->super(); if (super) { KlassInfoEntry* super_e = _cit->lookup(super); if (super_e) { @@ -608,18 +605,12 @@ void KlassInfoHisto::print_class_stats(outputStream* st, case KlassSizeStats::_index_inst_size: case KlassSizeStats::_index_inst_count: case KlassSizeStats::_index_method_count: -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL - st->print(str_fmt(width_table[c]), "-"); -PRAGMA_DIAG_POP + st->print("%*s", width_table[c], "-"); break; default: { double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes; -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL - st->print(perc_fmt(width_table[c]), perc); -PRAGMA_DIAG_POP + st->print("%*.1f%%", width_table[c]-1, perc); } } } diff --git a/hotspot/src/share/vm/memory/heapInspection.hpp b/hotspot/src/share/vm/memory/heapInspection.hpp index 9e312206b2e..97197b1bc5e 100644 --- a/hotspot/src/share/vm/memory/heapInspection.hpp +++ b/hotspot/src/share/vm/memory/heapInspection.hpp @@ -313,32 +313,13 @@ class KlassInfoHisto : public StackObj { return HeapWordSize * x->size(); } - // returns a format string to print a julong with the given width. E.g, - // printf(num_fmt(6), julong(10)) would print out the number 10 with 4 - // leading spaces. -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED - static void print_julong(outputStream* st, int width, julong n) { int num_spaces = width - julong_width(n); if (num_spaces > 0) { - st->print(str_fmt(num_spaces), ""); + st->print("%*s", num_spaces, ""); } st->print(JULONG_FORMAT, n); } -PRAGMA_DIAG_POP - - static char* perc_fmt(int width) { - static char buf[32]; - jio_snprintf(buf, sizeof(buf), "%%%d.1f%%%%", width-1); - return buf; - } - - static char* str_fmt(int width) { - static char buf[32]; - jio_snprintf(buf, sizeof(buf), "%%%ds", width); - return buf; - } static int julong_width(julong n) { if (n == 0) { diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 71507120a70..0af64dbed96 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -90,7 +90,7 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { static GrowableArray* _global_klass_objects; static void collect_classes(Klass* k) { _global_klass_objects->append_if_missing(k); - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { // Add in the array classes too InstanceKlass* ik = InstanceKlass::cast(k); ik->array_klasses_do(collect_classes); @@ -126,7 +126,7 @@ static void rewrite_nofast_bytecode(Method* method) { static void rewrite_nofast_bytecodes_and_calculate_fingerprints() { for (int i = 0; i < _global_klass_objects->length(); i++) { Klass* k = _global_klass_objects->at(i); - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k); for (int i = 0; i < ik->methods()->length(); i++) { Method* m = ik->methods()->at(i); @@ -199,9 +199,9 @@ static void patch_klass_vtables(void** vtbl_list, void* new_vtable_start) { int n = _global_klass_objects->length(); for (int i = 0; i < n; i++) { Klass* obj = _global_klass_objects->at(i); - // Note oop_is_instance() is a virtual call. After patching vtables + // Note is_instance_klass() is a virtual call in debug. After patching vtables // all virtual calls on the dummy vtables will restore the original! - if (obj->oop_is_instance()) { + if (obj->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(obj); *(void**)ik = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, ik); ConstantPool* cp = ik->constants(); @@ -482,12 +482,12 @@ void VM_PopulateDumpSharedSpace::doit() { int num_type_array = 0, num_obj_array = 0, num_inst = 0; for (int i = 0; i < _global_klass_objects->length(); i++) { Klass* k = _global_klass_objects->at(i); - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { num_inst ++; - } else if (k->oop_is_objArray()) { + } else if (k->is_objArray_klass()) { num_obj_array ++; } else { - assert(k->oop_is_typeArray(), "sanity"); + assert(k->is_typeArray_klass(), "sanity"); num_type_array ++; } } @@ -540,7 +540,7 @@ void VM_PopulateDumpSharedSpace::doit() { NOT_PRODUCT(SystemDictionary::verify();) - // Copy the the symbol table, string table, and the system dictionary to the shared + // Copy the symbol table, string table, and the system dictionary to the shared // space in usable form. Copy the hashtable // buckets first [read-write], then copy the linked lists of entries // [read-only]. @@ -679,8 +679,8 @@ void VM_PopulateDumpSharedSpace::doit() { void MetaspaceShared::link_one_shared_class(Klass* obj, TRAPS) { Klass* k = obj; - if (k->oop_is_instance()) { - InstanceKlass* ik = (InstanceKlass*) k; + if (k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); // Link the class to cause the bytecodes to be rewritten and the // cpcache to be created. Class verification is done according // to -Xverify setting. @@ -690,7 +690,7 @@ void MetaspaceShared::link_one_shared_class(Klass* obj, TRAPS) { } void MetaspaceShared::check_one_shared_class(Klass* k) { - if (k->oop_is_instance() && InstanceKlass::cast(k)->check_sharing_error_state()) { + if (k->is_instance_klass() && InstanceKlass::cast(k)->check_sharing_error_state()) { _check_classes_made_progress = true; } } diff --git a/hotspot/src/share/vm/memory/oopFactory.cpp b/hotspot/src/share/vm/memory/oopFactory.cpp index 1e214b328d3..3693deb5007 100644 --- a/hotspot/src/share/vm/memory/oopFactory.cpp +++ b/hotspot/src/share/vm/memory/oopFactory.cpp @@ -81,10 +81,9 @@ typeArrayOop oopFactory::new_typeArray_nozero(BasicType type, int length, TRAPS) objArrayOop oopFactory::new_objArray(Klass* klass, int length, TRAPS) { assert(klass->is_klass(), "must be instance class"); - if (klass->oop_is_array()) { - return ((ArrayKlass*)klass)->allocate_arrayArray(1, length, THREAD); + if (klass->is_array_klass()) { + return ArrayKlass::cast(klass)->allocate_arrayArray(1, length, THREAD); } else { - assert (klass->oop_is_instance(), "new object array with klass not an InstanceKlass"); - return ((InstanceKlass*)klass)->allocate_objArray(1, length, THREAD); + return InstanceKlass::cast(klass)->allocate_objArray(1, length, THREAD); } } diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index fa22f5bfdcc..7ec9cfa3a99 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -409,7 +409,7 @@ void Universe::genesis(TRAPS) { int i = 0; while (i < size) { // Allocate dummy in old generation - oop dummy = InstanceKlass::cast(SystemDictionary::Object_klass())->allocate_instance(CHECK); + oop dummy = SystemDictionary::Object_klass()->allocate_instance(CHECK); dummy_array->obj_at_put(i++, dummy); } { @@ -484,8 +484,8 @@ void Universe::initialize_basic_type_mirrors(TRAPS) { _mirrors[T_LONG] = _long_mirror; _mirrors[T_SHORT] = _short_mirror; _mirrors[T_VOID] = _void_mirror; - //_mirrors[T_OBJECT] = InstanceKlass::cast(_object_klass)->java_mirror(); - //_mirrors[T_ARRAY] = InstanceKlass::cast(_object_klass)->java_mirror(); + //_mirrors[T_OBJECT] = _object_klass->java_mirror(); + //_mirrors[T_ARRAY] = _object_klass->java_mirror(); } void Universe::fixup_mirrors(TRAPS) { @@ -545,9 +545,8 @@ void Universe::reinitialize_vtable_of(KlassHandle k_h, TRAPS) { Klass* ko = k_h(); klassVtable* vt = ko->vtable(); if (vt) vt->initialize_vtable(false, CHECK); - if (ko->oop_is_instance()) { - InstanceKlass* ik = (InstanceKlass*)ko; - for (KlassHandle s_h(THREAD, ik->subklass()); + if (ko->is_instance_klass()) { + for (KlassHandle s_h(THREAD, ko->subklass()); s_h() != NULL; s_h = KlassHandle(THREAD, s_h()->next_sibling())) { reinitialize_vtable_of(s_h, CHECK); @@ -998,8 +997,8 @@ bool universe_post_init() { // Setup static method for registering finalizers // The finalizer klass must be linked before looking up the method, in // case it needs to get rewritten. - InstanceKlass::cast(SystemDictionary::Finalizer_klass())->link_class(CHECK_false); - Method* m = InstanceKlass::cast(SystemDictionary::Finalizer_klass())->find_method( + SystemDictionary::Finalizer_klass()->link_class(CHECK_false); + Method* m = SystemDictionary::Finalizer_klass()->find_method( vmSymbols::register_method_name(), vmSymbols::register_method_signature()); if (m == NULL || !m->is_static()) { @@ -1009,8 +1008,8 @@ bool universe_post_init() { Universe::_finalizer_register_cache->init( SystemDictionary::Finalizer_klass(), m); - InstanceKlass::cast(SystemDictionary::misc_Unsafe_klass())->link_class(CHECK_false); - m = InstanceKlass::cast(SystemDictionary::misc_Unsafe_klass())->find_method( + SystemDictionary::internal_Unsafe_klass()->link_class(CHECK_false); + m = SystemDictionary::internal_Unsafe_klass()->find_method( vmSymbols::throwIllegalAccessError_name(), vmSymbols::void_method_signature()); if (m != NULL && !m->is_static()) { @@ -1020,11 +1019,11 @@ bool universe_post_init() { return false; // initialization failed (cannot throw exception yet) } Universe::_throw_illegal_access_error_cache->init( - SystemDictionary::misc_Unsafe_klass(), m); + SystemDictionary::internal_Unsafe_klass(), m); // Setup method for registering loaded classes in class loader vector - InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false); - m = InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature()); + SystemDictionary::ClassLoader_klass()->link_class(CHECK_false); + m = SystemDictionary::ClassLoader_klass()->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature()); if (m == NULL || m->is_static()) { tty->print_cr("Unable to link/verify ClassLoader.addClass method"); return false; // initialization failed (cannot throw exception yet) @@ -1033,8 +1032,8 @@ bool universe_post_init() { SystemDictionary::ClassLoader_klass(), m); // Setup method for checking protection domain - InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass())->link_class(CHECK_false); - m = InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass())-> + SystemDictionary::ProtectionDomain_klass()->link_class(CHECK_false); + m = SystemDictionary::ProtectionDomain_klass()-> find_method(vmSymbols::impliesCreateAccessControlContext_name(), vmSymbols::void_boolean_signature()); // Allow NULL which should only happen with bootstrapping. diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index e81a353f53b..0a9dbd28cc4 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -50,7 +50,7 @@ class ArrayKlass: public Klass { public: // Testing operation - bool oop_is_array_slow() const { return true; } + DEBUG_ONLY(bool is_array_klass_slow() const { return true; }) // Instance variables int dimension() const { return _dimension; } @@ -86,8 +86,8 @@ class ArrayKlass: public Klass { // Casting from Klass* static ArrayKlass* cast(Klass* k) { - assert(k->oop_is_array(), "cast to ArrayKlass"); - return (ArrayKlass*) k; + assert(k->is_array_klass(), "cast to ArrayKlass"); + return static_cast(k); } GrowableArray* compute_secondary_supers(int num_extra_slots); diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 5d3c61d2a41..006a1e5b5a6 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -178,7 +178,7 @@ int ConstantPool::cp_to_object_index(int cp_index) { return (i < 0) ? _no_index_sentinel : i; } -void ConstantPool::trace_class_resolution(constantPoolHandle this_cp, KlassHandle k) { +void ConstantPool::trace_class_resolution(const constantPoolHandle& this_cp, KlassHandle k) { ResourceMark rm; int line_number = -1; const char * source_file = NULL; @@ -198,16 +198,16 @@ void ConstantPool::trace_class_resolution(constantPoolHandle this_cp, KlassHandl if (source_file != NULL) { tty->print("RESOLVE %s %s %s:%d\n", this_cp->pool_holder()->external_name(), - InstanceKlass::cast(k())->external_name(), source_file, line_number); + k->external_name(), source_file, line_number); } else { tty->print("RESOLVE %s %s\n", this_cp->pool_holder()->external_name(), - InstanceKlass::cast(k())->external_name()); + k->external_name()); } } } -Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, +Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which, bool save_resolution_error, TRAPS) { assert(THREAD->is_Java_thread(), "must be a Java thread"); @@ -269,7 +269,7 @@ Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data(); this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM - if (TraceClassResolution && !k->oop_is_array()) { + if (TraceClassResolution && !k->is_array_klass()) { // skip resolving the constant pool so that this code gets // called the next time some bytecodes refer to this class. trace_class_resolution(this_cp, k); @@ -288,7 +288,7 @@ Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, // by compiler and exception handling. Also used to avoid classloads for // instanceof operations. Returns NULL if the class has not been loaded or // if the verification of constant pool failed -Klass* ConstantPool::klass_at_if_loaded(constantPoolHandle this_cp, int which) { +Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int which) { CPSlot entry = this_cp->slot_at(which); if (entry.is_resolved()) { assert(entry.get_klass()->is_klass(), "must be"); @@ -321,12 +321,12 @@ Klass* ConstantPool::klass_at_if_loaded(constantPoolHandle this_cp, int which) { } -Klass* ConstantPool::klass_ref_at_if_loaded(constantPoolHandle this_cp, int which) { +Klass* ConstantPool::klass_ref_at_if_loaded(const constantPoolHandle& this_cp, int which) { return klass_at_if_loaded(this_cp, this_cp->klass_ref_index_at(which)); } -Method* ConstantPool::method_at_if_loaded(constantPoolHandle cpool, +Method* ConstantPool::method_at_if_loaded(const constantPoolHandle& cpool, int which) { if (cpool->cache() == NULL) return NULL; // nothing to load yet int cache_index = decode_cpcache_index(which, true); @@ -342,14 +342,14 @@ Method* ConstantPool::method_at_if_loaded(constantPoolHandle cpool, } -bool ConstantPool::has_appendix_at_if_loaded(constantPoolHandle cpool, int which) { +bool ConstantPool::has_appendix_at_if_loaded(const constantPoolHandle& cpool, int which) { if (cpool->cache() == NULL) return false; // nothing to load yet int cache_index = decode_cpcache_index(which, true); ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); return e->has_appendix(); } -oop ConstantPool::appendix_at_if_loaded(constantPoolHandle cpool, int which) { +oop ConstantPool::appendix_at_if_loaded(const constantPoolHandle& cpool, int which) { if (cpool->cache() == NULL) return NULL; // nothing to load yet int cache_index = decode_cpcache_index(which, true); ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); @@ -357,14 +357,14 @@ oop ConstantPool::appendix_at_if_loaded(constantPoolHandle cpool, int which) { } -bool ConstantPool::has_method_type_at_if_loaded(constantPoolHandle cpool, int which) { +bool ConstantPool::has_method_type_at_if_loaded(const constantPoolHandle& cpool, int which) { if (cpool->cache() == NULL) return false; // nothing to load yet int cache_index = decode_cpcache_index(which, true); ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); return e->has_method_type(); } -oop ConstantPool::method_type_at_if_loaded(constantPoolHandle cpool, int which) { +oop ConstantPool::method_type_at_if_loaded(const constantPoolHandle& cpool, int which) { if (cpool->cache() == NULL) return NULL; // nothing to load yet int cache_index = decode_cpcache_index(which, true); ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); @@ -434,15 +434,15 @@ int ConstantPool::remap_instruction_operand_from_cache(int operand) { } -void ConstantPool::verify_constant_pool_resolve(constantPoolHandle this_cp, KlassHandle k, TRAPS) { - if (k->oop_is_instance() || k->oop_is_objArray()) { +void ConstantPool::verify_constant_pool_resolve(const constantPoolHandle& this_cp, KlassHandle k, TRAPS) { + if (k->is_instance_klass() || k->is_objArray_klass()) { instanceKlassHandle holder (THREAD, this_cp->pool_holder()); - Klass* elem = k->oop_is_instance() ? k() : ObjArrayKlass::cast(k())->bottom_klass(); + Klass* elem = k->is_instance_klass() ? k() : ObjArrayKlass::cast(k())->bottom_klass(); KlassHandle element (THREAD, elem); // The element type could be a typeArray - we only need the access check if it is // an reference to another class - if (element->oop_is_instance()) { + if (element->is_instance_klass()) { LinkResolver::check_klass_accessability(holder, element, CHECK); } } @@ -502,7 +502,7 @@ BasicType ConstantPool::basic_type_for_signature_at(int which) { } -void ConstantPool::resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS) { +void ConstantPool::resolve_string_constants_impl(const constantPoolHandle& this_cp, TRAPS) { for (int index = 1; index < this_cp->length(); index++) { // Index 0 is unused if (this_cp->tag_at(index).is_string()) { this_cp->string_at(index, CHECK); @@ -526,7 +526,7 @@ bool ConstantPool::resolve_class_constants(TRAPS) { return true; } -Symbol* ConstantPool::exception_message(constantPoolHandle this_cp, int which, constantTag tag, oop pending_exception) { +Symbol* ConstantPool::exception_message(const constantPoolHandle& this_cp, int which, constantTag tag, oop pending_exception) { // Dig out the detailed message to reuse if possible Symbol* message = java_lang_Throwable::detail_message(pending_exception); if (message != NULL) { @@ -554,7 +554,7 @@ Symbol* ConstantPool::exception_message(constantPoolHandle this_cp, int which, c return message; } -void ConstantPool::throw_resolution_error(constantPoolHandle this_cp, int which, TRAPS) { +void ConstantPool::throw_resolution_error(const constantPoolHandle& this_cp, int which, TRAPS) { Symbol* message = NULL; Symbol* error = SystemDictionary::find_resolution_error(this_cp, which, &message); assert(error != NULL && message != NULL, "checking"); @@ -565,7 +565,7 @@ void ConstantPool::throw_resolution_error(constantPoolHandle this_cp, int which, // If resolution for Class, MethodHandle or MethodType fails, save the exception // in the resolution error table, so that the same exception is thrown again. -void ConstantPool::save_and_throw_exception(constantPoolHandle this_cp, int which, +void ConstantPool::save_and_throw_exception(const constantPoolHandle& this_cp, int which, constantTag tag, TRAPS) { Symbol* error = PENDING_EXCEPTION->klass()->name(); @@ -603,7 +603,7 @@ void ConstantPool::save_and_throw_exception(constantPoolHandle this_cp, int whic // Called to resolve constants in the constant pool and return an oop. // Some constant pool entries cache their resolved oop. This is also // called to create oops from constants to use in arguments for invokedynamic -oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_cp, int index, int cache_index, TRAPS) { +oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index, TRAPS) { oop result_oop = NULL; Handle throw_exception; @@ -756,7 +756,7 @@ oop ConstantPool::uncached_string_at(int which, TRAPS) { } -oop ConstantPool::resolve_bootstrap_specifier_at_impl(constantPoolHandle this_cp, int index, TRAPS) { +oop ConstantPool::resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS) { assert(this_cp->tag_at(index).is_invoke_dynamic(), "Corrupted constant pool"); Handle bsm; @@ -794,7 +794,7 @@ oop ConstantPool::resolve_bootstrap_specifier_at_impl(constantPoolHandle this_cp return info(); } -oop ConstantPool::string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS) { +oop ConstantPool::string_at_impl(const constantPoolHandle& this_cp, int which, int obj_index, TRAPS) { // If the string has already been interned, this entry will be non-null oop str = this_cp->resolved_references()->obj_at(obj_index); if (str != NULL) return str; @@ -830,7 +830,7 @@ void ConstantPool::unreference_symbols() { // Compare this constant pool's entry at index1 to the constant pool // cp2's entry at index2. -bool ConstantPool::compare_entry_to(int index1, constantPoolHandle cp2, +bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2, int index2, TRAPS) { // The error tags are equivalent to non-error tags when comparing @@ -1056,7 +1056,7 @@ void ConstantPool::resize_operands(int delta_len, int delta_size, TRAPS) { // Extend the operands array with the length and size of the ext_cp operands. // Used in RedefineClasses for CP merge. -void ConstantPool::extend_operands(constantPoolHandle ext_cp, TRAPS) { +void ConstantPool::extend_operands(const constantPoolHandle& ext_cp, TRAPS) { int delta_len = operand_array_length(ext_cp->operands()); if (delta_len == 0) { return; // nothing to do @@ -1096,8 +1096,8 @@ void ConstantPool::shrink_operands(int new_len, TRAPS) { } // end shrink_operands() -void ConstantPool::copy_operands(constantPoolHandle from_cp, - constantPoolHandle to_cp, +void ConstantPool::copy_operands(const constantPoolHandle& from_cp, + const constantPoolHandle& to_cp, TRAPS) { int from_oplen = operand_array_length(from_cp->operands()); @@ -1160,8 +1160,8 @@ void ConstantPool::copy_operands(constantPoolHandle from_cp, // Copy this constant pool's entries at start_i to end_i (inclusive) // to the constant pool to_cp's entries starting at to_i. A total of // (end_i - start_i) + 1 entries are copied. -void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, - constantPoolHandle to_cp, int to_i, TRAPS) { +void ConstantPool::copy_cp_to_impl(const constantPoolHandle& from_cp, int start_i, int end_i, + const constantPoolHandle& to_cp, int to_i, TRAPS) { int dest_i = to_i; // leave original alone for debug purposes @@ -1191,8 +1191,8 @@ void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int // Copy this constant pool's entry at from_i to the constant pool // to_cp's entry at to_i. -void ConstantPool::copy_entry_to(constantPoolHandle from_cp, int from_i, - constantPoolHandle to_cp, int to_i, +void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i, + const constantPoolHandle& to_cp, int to_i, TRAPS) { int tag = from_cp->tag_at(from_i).value(); @@ -1339,7 +1339,7 @@ void ConstantPool::copy_entry_to(constantPoolHandle from_cp, int from_i, // constant pool's entry at pattern_i. Returns the index of a // matching entry or zero (0) if there is no matching entry. int ConstantPool::find_matching_entry(int pattern_i, - constantPoolHandle search_cp, TRAPS) { + const constantPoolHandle& search_cp, TRAPS) { // index zero (0) is not used for (int i = 1; i < search_cp->length(); i++) { @@ -1355,7 +1355,7 @@ int ConstantPool::find_matching_entry(int pattern_i, // Compare this constant pool's bootstrap specifier at idx1 to the constant pool // cp2's bootstrap specifier at idx2. -bool ConstantPool::compare_operand_to(int idx1, constantPoolHandle cp2, int idx2, TRAPS) { +bool ConstantPool::compare_operand_to(int idx1, const constantPoolHandle& cp2, int idx2, TRAPS) { int k1 = operand_bootstrap_method_ref_index_at(idx1); int k2 = cp2->operand_bootstrap_method_ref_index_at(idx2); bool match = compare_entry_to(k1, cp2, k2, CHECK_false); @@ -1382,7 +1382,7 @@ bool ConstantPool::compare_operand_to(int idx1, constantPoolHandle cp2, int idx2 // 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. int ConstantPool::find_matching_operand(int pattern_i, - constantPoolHandle search_cp, int search_len, TRAPS) { + const constantPoolHandle& search_cp, int search_len, TRAPS) { for (int i = 0; i < search_len; i++) { bool found = compare_operand_to(pattern_i, search_cp, i, CHECK_(-1)); if (found) { @@ -1843,7 +1843,7 @@ void ConstantPool::preload_and_initialize_all_classes(ConstantPool* obj, TRAPS) if (cp->tag_at(i).is_unresolved_klass()) { // This will force loading of the class Klass* klass = cp->klass_at(i, CHECK); - if (klass->oop_is_instance()) { + if (klass->is_instance_klass()) { // Force initialization of class InstanceKlass::cast(klass)->initialize(CHECK); } diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index dca3a2f4d31..99d77253be9 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -604,15 +604,15 @@ class ConstantPool : public Metadata { return offset; } // Compare a bootsrap specifier in the operands arrays - bool compare_operand_to(int bootstrap_specifier_index1, constantPoolHandle cp2, + bool compare_operand_to(int bootstrap_specifier_index1, const constantPoolHandle& cp2, int bootstrap_specifier_index2, TRAPS); // Find a bootsrap specifier in the operands array - int find_matching_operand(int bootstrap_specifier_index, constantPoolHandle search_cp, + int find_matching_operand(int bootstrap_specifier_index, const constantPoolHandle& search_cp, int operands_cur_len, TRAPS); // Resize the operands array with delta_len and delta_size void resize_operands(int delta_len, int delta_size, TRAPS); // Extend the operands array with the length and size of the ext_cp operands - void extend_operands(constantPoolHandle ext_cp, TRAPS); + void extend_operands(const constantPoolHandle& ext_cp, TRAPS); // Shrink the operands array to a smaller array with new_len length void shrink_operands(int new_len, TRAPS); @@ -735,13 +735,13 @@ class ConstantPool : public Metadata { friend class SystemDictionary; // Used by compiler to prevent classloading. - static Method* method_at_if_loaded (constantPoolHandle this_cp, int which); - static bool has_appendix_at_if_loaded (constantPoolHandle this_cp, int which); - static oop appendix_at_if_loaded (constantPoolHandle this_cp, int which); - static bool has_method_type_at_if_loaded (constantPoolHandle this_cp, int which); - static oop method_type_at_if_loaded (constantPoolHandle this_cp, int which); - static Klass* klass_at_if_loaded (constantPoolHandle this_cp, int which); - static Klass* klass_ref_at_if_loaded (constantPoolHandle this_cp, int which); + static Method* method_at_if_loaded (const constantPoolHandle& this_cp, int which); + static bool has_appendix_at_if_loaded (const constantPoolHandle& this_cp, int which); + static oop appendix_at_if_loaded (const constantPoolHandle& this_cp, int which); + static bool has_method_type_at_if_loaded (const constantPoolHandle& this_cp, int which); + static oop method_type_at_if_loaded (const constantPoolHandle& this_cp, int which); + static Klass* klass_at_if_loaded (const constantPoolHandle& this_cp, int which); + static Klass* klass_ref_at_if_loaded (const constantPoolHandle& this_cp, int which); // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the // future by other Java code. These take constant pool indices rather than @@ -797,38 +797,38 @@ class ConstantPool : public Metadata { } // Performs the LinkResolver checks - static void verify_constant_pool_resolve(constantPoolHandle this_cp, KlassHandle klass, TRAPS); + static void verify_constant_pool_resolve(const constantPoolHandle& this_cp, KlassHandle klass, TRAPS); // Implementation of methods that needs an exposed 'this' pointer, in order to // handle GC while executing the method - static Klass* klass_at_impl(constantPoolHandle this_cp, int which, + static Klass* klass_at_impl(const constantPoolHandle& this_cp, int which, bool save_resolution_error, TRAPS); - static oop string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS); + static oop string_at_impl(const constantPoolHandle& this_cp, int which, int obj_index, TRAPS); - static void trace_class_resolution(constantPoolHandle this_cp, KlassHandle k); + static void trace_class_resolution(const constantPoolHandle& this_cp, KlassHandle k); // Resolve string constants (to prevent allocation during compilation) - static void resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS); + static void resolve_string_constants_impl(const constantPoolHandle& this_cp, TRAPS); - static oop resolve_constant_at_impl(constantPoolHandle this_cp, int index, int cache_index, TRAPS); - static oop resolve_bootstrap_specifier_at_impl(constantPoolHandle this_cp, int index, TRAPS); + static oop resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index, TRAPS); + static oop resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS); // Exception handling - static void throw_resolution_error(constantPoolHandle this_cp, int which, TRAPS); - static Symbol* exception_message(constantPoolHandle this_cp, int which, constantTag tag, oop pending_exception); - static void save_and_throw_exception(constantPoolHandle this_cp, int which, constantTag tag, TRAPS); + static void throw_resolution_error(const constantPoolHandle& this_cp, int which, TRAPS); + static Symbol* exception_message(const constantPoolHandle& this_cp, int which, constantTag tag, oop pending_exception); + static void save_and_throw_exception(const constantPoolHandle& this_cp, int which, constantTag tag, TRAPS); public: // Merging ConstantPool* support: - bool compare_entry_to(int index1, constantPoolHandle cp2, int index2, TRAPS); - void copy_cp_to(int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS) { + bool compare_entry_to(int index1, const constantPoolHandle& cp2, int index2, TRAPS); + void copy_cp_to(int start_i, int end_i, const constantPoolHandle& to_cp, int to_i, TRAPS) { constantPoolHandle h_this(THREAD, this); copy_cp_to_impl(h_this, start_i, end_i, to_cp, to_i, THREAD); } - static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS); - static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS); - static void copy_operands(constantPoolHandle from_cp, constantPoolHandle to_cp, TRAPS); - int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS); + static void copy_cp_to_impl(const constantPoolHandle& from_cp, int start_i, int end_i, const constantPoolHandle& to_cp, int to_i, TRAPS); + static void copy_entry_to(const constantPoolHandle& from_cp, int from_i, const constantPoolHandle& to_cp, int to_i, TRAPS); + static void copy_operands(const constantPoolHandle& from_cp, const constantPoolHandle& to_cp, TRAPS); + int find_matching_entry(int pattern_i, const constantPoolHandle& search_cp, TRAPS); int version() const { return _saved._version; } void set_version(int version) { _saved._version = version; } void increment_and_save_version(int version) { diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp index db65df2172c..6066a319e8f 100644 --- a/hotspot/src/share/vm/oops/cpCache.cpp +++ b/hotspot/src/share/vm/oops/cpCache.cpp @@ -246,7 +246,7 @@ void ConstantPoolCacheEntry::set_vtable_call(Bytecodes::Code invoke_code, method set_direct_or_vtable_call(invoke_code, method, index); } -void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, methodHandle method, int index) { +void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, const methodHandle& method, int index) { assert(method->method_holder()->verify_itable_index(index), ""); assert(invoke_code == Bytecodes::_invokeinterface, ""); InstanceKlass* interf = method->method_holder(); @@ -261,15 +261,15 @@ void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, method } -void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool, const CallInfo &call_info) { +void ConstantPoolCacheEntry::set_method_handle(const constantPoolHandle& cpool, const CallInfo &call_info) { set_method_handle_common(cpool, Bytecodes::_invokehandle, call_info); } -void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool, const CallInfo &call_info) { +void ConstantPoolCacheEntry::set_dynamic_call(const constantPoolHandle& cpool, const CallInfo &call_info) { set_method_handle_common(cpool, Bytecodes::_invokedynamic, call_info); } -void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, +void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle& cpool, Bytecodes::Code invoke_code, const CallInfo &call_info) { // NOTE: This CPCE can be the subject of data races. @@ -361,7 +361,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, } } -Method* ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) { +Method* ConstantPoolCacheEntry::method_if_resolved(const constantPoolHandle& cpool) { // Decode the action of set_method and set_interface_call Bytecodes::Code invoke_code = bytecode_1(); if (invoke_code != (Bytecodes::Code)0) { @@ -394,7 +394,7 @@ Method* ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) { int holder_index = cpool->uncached_klass_ref_index_at(constant_pool_index()); if (cpool->tag_at(holder_index).is_klass()) { Klass* klass = cpool->resolved_klass_at(holder_index); - if (!klass->oop_is_instance()) + if (!klass->is_instance_klass()) klass = SystemDictionary::Object_klass(); return InstanceKlass::cast(klass)->method_at_vtable(f2_as_index()); } @@ -406,7 +406,7 @@ Method* ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) { } -oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) { +oop ConstantPoolCacheEntry::appendix_if_resolved(const constantPoolHandle& cpool) { if (!has_appendix()) return NULL; const int ref_index = f2_as_index() + _indy_resolved_references_appendix_offset; @@ -415,7 +415,7 @@ oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) { } -oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) { +oop ConstantPoolCacheEntry::method_type_if_resolved(const constantPoolHandle& cpool) { if (!has_method_type()) return NULL; const int ref_index = f2_as_index() + _indy_resolved_references_method_type_offset; diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp index 435a1d6c4a7..cf6731da613 100644 --- a/hotspot/src/share/vm/oops/cpCache.hpp +++ b/hotspot/src/share/vm/oops/cpCache.hpp @@ -246,17 +246,17 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { void set_itable_call( Bytecodes::Code invoke_code, // the bytecode used; must be invokeinterface - methodHandle method, // the resolved interface method + const methodHandle& method, // the resolved interface method int itable_index // index into itable for the method ); void set_method_handle( - constantPoolHandle cpool, // holding constant pool (required for locking) + const constantPoolHandle& cpool, // holding constant pool (required for locking) const CallInfo &call_info // Call link information ); void set_dynamic_call( - constantPoolHandle cpool, // holding constant pool (required for locking) + const constantPoolHandle& cpool, // holding constant pool (required for locking) const CallInfo &call_info // Call link information ); @@ -276,7 +276,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { // resolution logic needs to make slightly different assessments about the // number and types of arguments. void set_method_handle_common( - constantPoolHandle cpool, // holding constant pool (required for locking) + const constantPoolHandle& cpool, // holding constant pool (required for locking) Bytecodes::Code invoke_code, // _invokehandle or _invokedynamic const CallInfo &call_info // Call link information ); @@ -291,9 +291,9 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { _indy_resolved_references_entries }; - Method* method_if_resolved(constantPoolHandle cpool); - oop appendix_if_resolved(constantPoolHandle cpool); - oop method_type_if_resolved(constantPoolHandle cpool); + Method* method_if_resolved(const constantPoolHandle& cpool); + oop appendix_if_resolved(const constantPoolHandle& cpool); + oop method_type_if_resolved(const constantPoolHandle& cpool); void set_parameter_size(int value); diff --git a/hotspot/src/share/vm/oops/fieldInfo.hpp b/hotspot/src/share/vm/oops/fieldInfo.hpp index 40a192bdcc0..cf456667a78 100644 --- a/hotspot/src/share/vm/oops/fieldInfo.hpp +++ b/hotspot/src/share/vm/oops/fieldInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -176,7 +176,7 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { return (_shorts[low_packed_offset] & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET; } - Symbol* name(constantPoolHandle cp) const { + Symbol* name(const constantPoolHandle& cp) const { int index = name_index(); if (is_internal()) { return lookup_symbol(index); @@ -184,7 +184,7 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { return cp->symbol_at(index); } - Symbol* signature(constantPoolHandle cp) const { + Symbol* signature(const constantPoolHandle& cp) const { int index = signature_index(); if (is_internal()) { return lookup_symbol(index); diff --git a/hotspot/src/share/vm/oops/fieldStreams.hpp b/hotspot/src/share/vm/oops/fieldStreams.hpp index 342c31f4fad..c7d2d2743cf 100644 --- a/hotspot/src/share/vm/oops/fieldStreams.hpp +++ b/hotspot/src/share/vm/oops/fieldStreams.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -79,7 +79,7 @@ class FieldStreamBase : public StackObj { return num_fields; } - FieldStreamBase(Array* fields, constantPoolHandle constants, int start, int limit) { + FieldStreamBase(Array* fields, const constantPoolHandle& constants, int start, int limit) { _fields = fields; _constants = constants; _index = start; @@ -91,7 +91,7 @@ class FieldStreamBase : public StackObj { } } - FieldStreamBase(Array* fields, constantPoolHandle constants) { + FieldStreamBase(Array* fields, const constantPoolHandle& constants) { _fields = fields; _constants = constants; _index = 0; @@ -251,7 +251,7 @@ class InternalFieldStream : public FieldStreamBase { class AllFieldStream : public FieldStreamBase { public: - AllFieldStream(Array* fields, constantPoolHandle constants): FieldStreamBase(fields, constants) {} + AllFieldStream(Array* fields, const constantPoolHandle& constants): FieldStreamBase(fields, constants) {} AllFieldStream(InstanceKlass* k): FieldStreamBase(k->fields(), k->constants()) {} AllFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants()) {} }; diff --git a/hotspot/src/share/vm/oops/generateOopMap.cpp b/hotspot/src/share/vm/oops/generateOopMap.cpp index 2207e8c814e..53ec05ef6ea 100644 --- a/hotspot/src/share/vm/oops/generateOopMap.cpp +++ b/hotspot/src/share/vm/oops/generateOopMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -222,7 +222,7 @@ void RetTableEntry::add_delta(int bci, int delta) { } } -void RetTable::compute_ret_table(methodHandle method) { +void RetTable::compute_ret_table(const methodHandle& method) { BytecodeStream i(method); Bytecodes::Code bytecode; @@ -2039,7 +2039,7 @@ void GenerateOopMap::print_time() { // // ============ Main Entry Point =========== // -GenerateOopMap::GenerateOopMap(methodHandle method) { +GenerateOopMap::GenerateOopMap(const methodHandle& method) { // We have to initialize all variables here, that can be queried directly _method = method; _max_locals=0; diff --git a/hotspot/src/share/vm/oops/generateOopMap.hpp b/hotspot/src/share/vm/oops/generateOopMap.hpp index 48c49f443e9..8822ee0d839 100644 --- a/hotspot/src/share/vm/oops/generateOopMap.hpp +++ b/hotspot/src/share/vm/oops/generateOopMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -78,7 +78,7 @@ class RetTable VALUE_OBJ_CLASS_SPEC { void add_jsr(int return_bci, int target_bci); // Adds entry to list public: RetTable() { _first = NULL; } - void compute_ret_table(methodHandle method); + void compute_ret_table(const methodHandle& method); void update_ret_table(int bci, int delta); RetTableEntry* find_jsrs_for_target(int targBci); }; @@ -462,7 +462,7 @@ class GenerateOopMap VALUE_OBJ_CLASS_SPEC { friend class RelocCallback; public: - GenerateOopMap(methodHandle method); + GenerateOopMap(const methodHandle& method); // Compute the map. void compute_map(TRAPS); @@ -537,7 +537,7 @@ class ResolveOopMapConflicts: public GenerateOopMap { #endif public: - ResolveOopMapConflicts(methodHandle method) : GenerateOopMap(method) { _must_clear_locals = false; }; + ResolveOopMapConflicts(const methodHandle& method) : GenerateOopMap(method) { _must_clear_locals = false; }; methodHandle do_potential_rewrite(TRAPS); bool must_clear_locals() const { return _must_clear_locals; } @@ -562,7 +562,7 @@ class GeneratePairingInfo: public GenerateOopMap { int stack_top) {} virtual void fill_init_vars (GrowableArray *init_vars) {} public: - GeneratePairingInfo(methodHandle method) : GenerateOopMap(method) {}; + GeneratePairingInfo(const methodHandle& method) : GenerateOopMap(method) {}; // Call compute_map(CHECK) to generate info. }; diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index f01521cc009..03584ee0320 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -742,7 +742,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { // A class could already be verified, since it has been reflected upon. this_k->link_class(CHECK); - DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_k()), -1); + DTRACE_CLASSINIT_PROBE(required, this_k(), -1); bool wait = false; @@ -765,19 +765,19 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { // Step 3 if (this_k->is_being_initialized() && this_k->is_reentrant_initialization(self)) { - DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_k()), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(recursive, this_k(), -1,wait); return; } // Step 4 if (this_k->is_initialized()) { - DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_k()), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(concurrent, this_k(), -1,wait); return; } // Step 5 if (this_k->is_in_error_state()) { - DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_k()), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(erroneous, this_k(), -1,wait); ResourceMark rm(THREAD); const char* desc = "Could not initialize class "; const char* className = this_k->external_name(); @@ -810,7 +810,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { this_k->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, superclass initialization error is thrown below } - DTRACE_CLASSINIT_PROBE_WAIT(super__failed, InstanceKlass::cast(this_k()), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(super__failed, this_k(), -1,wait); THROW_OOP(e()); } } @@ -826,7 +826,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { { assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl"); JavaThread* jt = (JavaThread*)THREAD; - DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_k()), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(clinit, this_k(), -1,wait); // Timer includes any side effects of class initialization (resolution, // etc), but not recursive entry into call_class_initializer(). PerfClassTraceTime timer(ClassLoader::perf_class_init_time(), @@ -860,7 +860,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError JvmtiExport::clear_detected_exception((JavaThread*)THREAD); } - DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_k()), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(error, this_k(), -1,wait); if (e->is_a(SystemDictionary::Error_klass())) { THROW_OOP(e()); } else { @@ -870,7 +870,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { &args); } } - DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_k()), -1,wait); + DTRACE_CLASSINIT_PROBE_WAIT(end, this_k(), -1,wait); } @@ -907,7 +907,7 @@ void InstanceKlass::add_implementor(Klass* k) { // Filter out subclasses whose supers already implement me. // (Note: CHA must walk subclasses of direct implementors // in order to locate indirect implementors.) - Klass* sk = InstanceKlass::cast(k)->super(); + Klass* sk = k->super(); if (sk != NULL && InstanceKlass::cast(sk)->implements_interface(this)) // We only need to check one immediate superclass, since the // implements_interface query looks at transitive_interfaces. @@ -955,8 +955,7 @@ bool InstanceKlass::can_be_primary_super_slow() const { GrowableArray* InstanceKlass::compute_secondary_supers(int num_extra_slots) { // The secondaries are the implemented interfaces. - InstanceKlass* ik = InstanceKlass::cast(this); - Array* interfaces = ik->transitive_interfaces(); + Array* interfaces = transitive_interfaces(); int num_secondaries = num_extra_slots + interfaces->length(); if (num_secondaries == 0) { // Must share this for correct bootstrapping! @@ -1141,7 +1140,7 @@ void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_k, TRAP } -void InstanceKlass::mask_for(methodHandle method, int bci, +void InstanceKlass::mask_for(const methodHandle& method, int bci, InterpreterOopMap* entry_for) { // Dirty read, then double-check under a lock. if (_oop_map_cache == NULL) { @@ -1532,7 +1531,7 @@ Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, O if (method != NULL) { return method; } - klass = InstanceKlass::cast(klass)->super(); + klass = klass->super(); overpass_local_mode = skip_overpass; // Always ignore overpass methods in superclasses } return NULL; @@ -1541,13 +1540,13 @@ Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, O #ifdef ASSERT // search through class hierarchy and return true if this class or // one of the superclasses was redefined -bool InstanceKlass::has_redefined_this_or_super() const { - const InstanceKlass* klass = this; +bool InstanceKlass::has_redefined_this_or_super() { + Klass* klass = this; while (klass != NULL) { - if (klass->has_been_redefined()) { + if (InstanceKlass::cast(klass)->has_been_redefined()) { return true; } - klass = InstanceKlass::cast(klass->super()); + klass = klass->super(); } return false; } @@ -1645,7 +1644,7 @@ void InstanceKlass::set_enclosing_method_indices(u2 class_index, // locking has to be done very carefully to avoid deadlocks // and/or other cache consistency problems. // -jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, methodHandle method_h) { +jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, const methodHandle& method_h) { size_t idnum = (size_t)method_h->method_idnum(); jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire(); size_t length = 0; @@ -1907,18 +1906,33 @@ nmethodBucket* nmethodBucket::add_dependent_nmethod(nmethodBucket* deps, nmethod // Decrement count of the nmethod in the dependency list and remove // the bucket completely when the count goes to 0. This method must // find a corresponding bucket otherwise there's a bug in the -// recording of dependencies. Returns true if the bucket is ready for reclamation. -// -bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) { +// recording of dependencies. Returns true if the bucket was deleted, +// or marked ready for reclaimation. +bool nmethodBucket::remove_dependent_nmethod(nmethodBucket** deps, nmethod* nm, bool delete_immediately) { assert_locked_or_safepoint(CodeCache_lock); - for (nmethodBucket* b = deps; b != NULL; b = b->next()) { + nmethodBucket* first = *deps; + nmethodBucket* last = NULL; + + for (nmethodBucket* b = first; b != NULL; b = b->next()) { if (nm == b->get_nmethod()) { int val = b->decrement(); guarantee(val >= 0, "Underflow: %d", val); - return (val == 0); + if (val == 0) { + if (delete_immediately) { + if (last == NULL) { + *deps = b->next(); + } else { + last->set_next(b->next()); + } + delete b; + } + } + return true; } + last = b; } + #ifdef ASSERT tty->print_raw_cr("### can't find dependent nmethod"); nm->print(); @@ -1927,6 +1941,12 @@ bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) { return false; } +// Convenience overload, for callers that don't want to delete the nmethodBucket entry. +bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) { + nmethodBucket** deps_addr = &deps; + return remove_dependent_nmethod(deps_addr, nm, false /* Don't delete */); +} + // // Reclaim all unused buckets. Returns new head of the list. // @@ -2013,10 +2033,10 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) { _dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm); } -void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { +void InstanceKlass::remove_dependent_nmethod(nmethod* nm, bool delete_immediately) { assert_locked_or_safepoint(CodeCache_lock); - if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) { + if (nmethodBucket::remove_dependent_nmethod(&_dependencies, nm, delete_immediately)) { set_has_unloaded_dependent(true); } } @@ -2031,6 +2051,13 @@ bool InstanceKlass::is_dependent_nmethod(nmethod* nm) { } #endif //PRODUCT +void InstanceKlass::clean_weak_instanceklass_links(BoolObjectClosure* is_alive) { + clean_implementors_list(is_alive); + clean_method_data(is_alive); + + clean_dependent_nmethods(); +} + void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { assert(class_loader_data()->is_alive(is_alive), "this klass should be live"); if (is_interface()) { @@ -2297,32 +2324,18 @@ const char* InstanceKlass::signature_name() const { // different verisons of is_same_class_package bool InstanceKlass::is_same_class_package(Klass* class2) { - Klass* class1 = this; - oop classloader1 = InstanceKlass::cast(class1)->class_loader(); - Symbol* classname1 = class1->name(); - - if (class2->oop_is_objArray()) { + if (class2->is_objArray_klass()) { class2 = ObjArrayKlass::cast(class2)->bottom_klass(); } - oop classloader2; - if (class2->oop_is_instance()) { - classloader2 = InstanceKlass::cast(class2)->class_loader(); - } else { - assert(class2->oop_is_typeArray(), "should be type array"); - classloader2 = NULL; - } + oop classloader2 = class2->class_loader(); Symbol* classname2 = class2->name(); - return InstanceKlass::is_same_class_package(classloader1, classname1, + return InstanceKlass::is_same_class_package(class_loader(), name(), classloader2, classname2); } bool InstanceKlass::is_same_class_package(oop classloader2, Symbol* classname2) { - Klass* class1 = this; - oop classloader1 = InstanceKlass::cast(class1)->class_loader(); - Symbol* classname1 = class1->name(); - - return InstanceKlass::is_same_class_package(classloader1, classname1, + return InstanceKlass::is_same_class_package(class_loader(), name(), classloader2, classname2); } @@ -2385,7 +2398,7 @@ bool InstanceKlass::is_same_class_package(oop class_loader1, Symbol* class_name1 // Assumes name-signature match // "this" is InstanceKlass of super_method which must exist // note that the InstanceKlass of the method in the targetclassname has not always been created yet -bool InstanceKlass::is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS) { +bool InstanceKlass::is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS) { // Private methods can not be overridden if (super_method->is_private()) { return false; @@ -2411,7 +2424,7 @@ Klass* InstanceKlass::compute_enclosing_class_impl(instanceKlassHandle self, bool InstanceKlass::is_same_package_member_impl(instanceKlassHandle class1, Klass* class2_oop, TRAPS) { if (class2_oop == class1()) return true; - if (!class2_oop->oop_is_instance()) return false; + if (!class2_oop->is_instance_klass()) return false; instanceKlassHandle class2(THREAD, class2_oop); // must be in same package before we try anything else @@ -2882,7 +2895,8 @@ void InstanceKlass::print_on(outputStream* st) const { ((InstanceKlass*)this)->do_local_static_fields(&print_static_field); st->print_cr(BULLET"---- non-static fields (%d words):", nonstatic_field_size()); FieldPrinter print_nonstatic_field(st); - ((InstanceKlass*)this)->do_nonstatic_fields(&print_nonstatic_field); + InstanceKlass* ik = const_cast(this); + ik->do_nonstatic_fields(&print_nonstatic_field); st->print(BULLET"non-static oop maps: "); OopMapBlock* map = start_of_nonstatic_oop_maps(); @@ -2921,12 +2935,10 @@ void InstanceKlass::oop_print_on(oop obj, outputStream* st) { if (this == SystemDictionary::String_klass()) { typeArrayOop value = java_lang_String::value(obj); - juint offset = java_lang_String::offset(obj); juint length = java_lang_String::length(obj); if (value != NULL && value->is_typeArray() && - offset <= (juint) value->length() && - offset + length <= (juint) value->length()) { + length <= (juint) value->length()) { st->print(BULLET"string: "); java_lang_String::print(obj, st); st->cr(); @@ -2953,7 +2965,7 @@ void InstanceKlass::oop_print_on(oop obj, outputStream* st) { st->print_cr(BULLET"fake entry for oop_size: %d", java_lang_Class::oop_size(obj)); st->print_cr(BULLET"fake entry for static_oop_field_count: %d", java_lang_Class::static_oop_field_count(obj)); Klass* real_klass = java_lang_Class::as_Klass(obj); - if (real_klass != NULL && real_klass->oop_is_instance()) { + if (real_klass != NULL && real_klass->is_instance_klass()) { InstanceKlass::cast(real_klass)->do_local_static_fields(&print_field); } } else if (this == SystemDictionary::MethodType_klass()) { @@ -3546,3 +3558,199 @@ jint InstanceKlass::get_cached_class_file_len() { unsigned char * InstanceKlass::get_cached_class_file_bytes() { return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file); } + + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +class TestNmethodBucketContext { + public: + nmethod* _nmethodLast; + nmethod* _nmethodMiddle; + nmethod* _nmethodFirst; + + nmethodBucket* _bucketLast; + nmethodBucket* _bucketMiddle; + nmethodBucket* _bucketFirst; + + nmethodBucket* _bucketList; + + TestNmethodBucketContext() { + CodeCache_lock->lock_without_safepoint_check(); + + _nmethodLast = reinterpret_cast(0x8 * 0); + _nmethodMiddle = reinterpret_cast(0x8 * 1); + _nmethodFirst = reinterpret_cast(0x8 * 2); + + _bucketLast = new nmethodBucket(_nmethodLast, NULL); + _bucketMiddle = new nmethodBucket(_nmethodMiddle, _bucketLast); + _bucketFirst = new nmethodBucket(_nmethodFirst, _bucketMiddle); + + _bucketList = _bucketFirst; + } + + ~TestNmethodBucketContext() { + delete _bucketLast; + delete _bucketMiddle; + delete _bucketFirst; + + CodeCache_lock->unlock(); + } +}; + +class TestNmethodBucket { + public: + static void testRemoveDependentNmethodFirstDeleteImmediately() { + TestNmethodBucketContext c; + + nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodFirst, true /* delete */); + + assert(c._bucketList == c._bucketMiddle, "check"); + assert(c._bucketList->next() == c._bucketLast, "check"); + assert(c._bucketList->next()->next() == NULL, "check"); + + // Cleanup before context is deleted. + c._bucketFirst = NULL; + } + + static void testRemoveDependentNmethodMiddleDeleteImmediately() { + TestNmethodBucketContext c; + + nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodMiddle, true /* delete */); + + assert(c._bucketList == c._bucketFirst, "check"); + assert(c._bucketList->next() == c._bucketLast, "check"); + assert(c._bucketList->next()->next() == NULL, "check"); + + // Cleanup before context is deleted. + c._bucketMiddle = NULL; + } + + static void testRemoveDependentNmethodLastDeleteImmediately() { + TestNmethodBucketContext c; + + nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodLast, true /* delete */); + + assert(c._bucketList == c._bucketFirst, "check"); + assert(c._bucketList->next() == c._bucketMiddle, "check"); + assert(c._bucketList->next()->next() == NULL, "check"); + + // Cleanup before context is deleted. + c._bucketLast = NULL; + } + + static void testRemoveDependentNmethodFirstDeleteDeferred() { + TestNmethodBucketContext c; + + nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodFirst, false /* delete */); + + assert(c._bucketList == c._bucketFirst, "check"); + assert(c._bucketList->next() == c._bucketMiddle, "check"); + assert(c._bucketList->next()->next() == c._bucketLast, "check"); + assert(c._bucketList->next()->next()->next() == NULL, "check"); + + assert(c._bucketFirst->count() == 0, "check"); + assert(c._bucketMiddle->count() == 1, "check"); + assert(c._bucketLast->count() == 1, "check"); + } + + static void testRemoveDependentNmethodMiddleDeleteDeferred() { + TestNmethodBucketContext c; + + nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodMiddle, false /* delete */); + + assert(c._bucketList == c._bucketFirst, "check"); + assert(c._bucketList->next() == c._bucketMiddle, "check"); + assert(c._bucketList->next()->next() == c._bucketLast, "check"); + assert(c._bucketList->next()->next()->next() == NULL, "check"); + + assert(c._bucketFirst->count() == 1, "check"); + assert(c._bucketMiddle->count() == 0, "check"); + assert(c._bucketLast->count() == 1, "check"); + } + + static void testRemoveDependentNmethodLastDeleteDeferred() { + TestNmethodBucketContext c; + + nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodLast, false /* delete */); + + assert(c._bucketList == c._bucketFirst, "check"); + assert(c._bucketList->next() == c._bucketMiddle, "check"); + assert(c._bucketList->next()->next() == c._bucketLast, "check"); + assert(c._bucketList->next()->next()->next() == NULL, "check"); + + assert(c._bucketFirst->count() == 1, "check"); + assert(c._bucketMiddle->count() == 1, "check"); + assert(c._bucketLast->count() == 0, "check"); + } + + static void testRemoveDependentNmethodConvenienceFirst() { + TestNmethodBucketContext c; + + nmethodBucket::remove_dependent_nmethod(c._bucketList, c._nmethodFirst); + + assert(c._bucketList == c._bucketFirst, "check"); + assert(c._bucketList->next() == c._bucketMiddle, "check"); + assert(c._bucketList->next()->next() == c._bucketLast, "check"); + assert(c._bucketList->next()->next()->next() == NULL, "check"); + + assert(c._bucketFirst->count() == 0, "check"); + assert(c._bucketMiddle->count() == 1, "check"); + assert(c._bucketLast->count() == 1, "check"); + } + + static void testRemoveDependentNmethodConvenienceMiddle() { + TestNmethodBucketContext c; + + nmethodBucket::remove_dependent_nmethod(c._bucketList, c._nmethodMiddle); + + assert(c._bucketList == c._bucketFirst, "check"); + assert(c._bucketList->next() == c._bucketMiddle, "check"); + assert(c._bucketList->next()->next() == c._bucketLast, "check"); + assert(c._bucketList->next()->next()->next() == NULL, "check"); + + assert(c._bucketFirst->count() == 1, "check"); + assert(c._bucketMiddle->count() == 0, "check"); + assert(c._bucketLast->count() == 1, "check"); + } + + static void testRemoveDependentNmethodConvenienceLast() { + TestNmethodBucketContext c; + + nmethodBucket::remove_dependent_nmethod(c._bucketList, c._nmethodLast); + + assert(c._bucketList == c._bucketFirst, "check"); + assert(c._bucketList->next() == c._bucketMiddle, "check"); + assert(c._bucketList->next()->next() == c._bucketLast, "check"); + assert(c._bucketList->next()->next()->next() == NULL, "check"); + + assert(c._bucketFirst->count() == 1, "check"); + assert(c._bucketMiddle->count() == 1, "check"); + assert(c._bucketLast->count() == 0, "check"); + } + + static void testRemoveDependentNmethod() { + testRemoveDependentNmethodFirstDeleteImmediately(); + testRemoveDependentNmethodMiddleDeleteImmediately(); + testRemoveDependentNmethodLastDeleteImmediately(); + + testRemoveDependentNmethodFirstDeleteDeferred(); + testRemoveDependentNmethodMiddleDeleteDeferred(); + testRemoveDependentNmethodLastDeleteDeferred(); + + testRemoveDependentNmethodConvenienceFirst(); + testRemoveDependentNmethodConvenienceMiddle(); + testRemoveDependentNmethodConvenienceLast(); + } + + static void test() { + testRemoveDependentNmethod(); + } +}; + +void TestNmethodBucket_test() { + TestNmethodBucket::test(); +} + +#endif diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index be9501089b6..9eebfcb7010 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -414,7 +414,7 @@ class InstanceKlass: public Klass { }; // method override check - bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS); + bool is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS); // package bool is_same_class_package(Klass* class2); @@ -780,7 +780,7 @@ public: // jmethodID support static jmethodID get_jmethod_id(instanceKlassHandle ik_h, - methodHandle method_h); + const methodHandle& method_h); static jmethodID get_jmethod_id_fetch_or_update(instanceKlassHandle ik_h, size_t idnum, jmethodID new_id, jmethodID* new_jmeths, jmethodID* to_dealloc_id_p, @@ -827,7 +827,7 @@ public: // OopMapCache support OopMapCache* oop_map_cache() { return _oop_map_cache; } void set_oop_map_cache(OopMapCache *cache) { _oop_map_cache = cache; } - void mask_for(methodHandle method, int bci, InterpreterOopMap* entry); + void mask_for(const methodHandle& method, int bci, InterpreterOopMap* entry); // JNI identifier support (for static fields - for jni performance) JNIid* jni_ids() { return _jni_ids; } @@ -837,7 +837,7 @@ public: // maintenance of deoptimization dependencies int mark_dependent_nmethods(DepChange& changes); void add_dependent_nmethod(nmethod* nm); - void remove_dependent_nmethod(nmethod* nm); + void remove_dependent_nmethod(nmethod* nm, bool delete_immediately); // On-stack replacement support nmethod* osr_nmethods_head() const { return _osr_nmethods_head; }; @@ -862,7 +862,7 @@ public: #ifdef ASSERT // check whether this class or one of its superclasses was redefined - bool has_redefined_this_or_super() const; + bool has_redefined_this_or_super(); #endif // Access to the implementor of an interface. @@ -908,7 +908,9 @@ public: bool compute_is_subtype_of(Klass* k); bool can_be_primary_super_slow() const; int oop_size(oop obj) const { return size_helper(); } - bool oop_is_instance_slow() const { return true; } + // slow because it's a virtual call and used for verifying the layout_helper. + // Using the layout_helper bits, we can call is_instance_klass without a virtual call. + DEBUG_ONLY(bool is_instance_klass_slow() const { return true; }) // Iterators void do_local_static_fields(FieldClosure* cl); @@ -922,7 +924,8 @@ public: // Casting from Klass* static InstanceKlass* cast(Klass* k) { - assert(k == NULL || k->oop_is_instance(), "cast to InstanceKlass"); + assert(k != NULL, "k should not be null"); + assert(k->is_instance_klass(), "cast to InstanceKlass"); return static_cast(k); } @@ -1021,6 +1024,7 @@ public: void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed); #endif // INCLUDE_JVMTI + void clean_weak_instanceklass_links(BoolObjectClosure* is_alive); void clean_implementors_list(BoolObjectClosure* is_alive); void clean_method_data(BoolObjectClosure* is_alive); void clean_dependent_nmethods(); @@ -1349,6 +1353,7 @@ class nmethodBucket: public CHeapObj { static int mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes); static nmethodBucket* add_dependent_nmethod(nmethodBucket* deps, nmethod* nm); + static bool remove_dependent_nmethod(nmethodBucket** deps, nmethod* nm, bool delete_immediately); static bool remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm); static nmethodBucket* clean_dependent_nmethods(nmethodBucket* deps); #ifndef PRODUCT diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp index aa64aad4e01..107f9523296 100644 --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp @@ -40,7 +40,7 @@ int InstanceMirrorKlass::_offset_of_static_fields = 0; int InstanceMirrorKlass::instance_size(KlassHandle k) { - if (k() != NULL && k->oop_is_instance()) { + if (k() != NULL && k->is_instance_klass()) { return align_object_size(size_helper() + InstanceKlass::cast(k())->static_field_size()); } return size_helper(); @@ -65,7 +65,7 @@ int InstanceMirrorKlass::oop_size(oop obj) const { int InstanceMirrorKlass::compute_static_oop_field_count(oop obj) { Klass* k = java_lang_Class::as_Klass(obj); - if (k != NULL && k->oop_is_instance()) { + if (k != NULL && k->is_instance_klass()) { return InstanceKlass::cast(k)->static_oop_field_count(); } return 0; diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.inline.hpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.inline.hpp index 9d1e9c622be..cb416918d9e 100644 --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.inline.hpp +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.inline.hpp @@ -60,7 +60,7 @@ void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) { Klass* klass = java_lang_Class::as_Klass(obj); // We'll get NULL for primitive mirrors. if (klass != NULL) { - if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) { + if (klass->is_instance_klass() && InstanceKlass::cast(klass)->is_anonymous()) { // An anonymous class doesn't have its own class loader, so when handling // the java mirror for an anonymous class we need to make sure its class // loader data is claimed, this is done by calling do_cld explicitly. diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.cpp b/hotspot/src/share/vm/oops/instanceRefKlass.cpp index 31da264eeff..8dc309dbee2 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp @@ -82,8 +82,9 @@ void InstanceRefKlass::oop_verify_on(oop obj, outputStream* st) { // Verify next field oop next = java_lang_ref_Reference::next(obj); if (next != NULL) { - guarantee(next->is_oop(), "next field verify failed"); - guarantee(next->is_instanceRef(), "next field verify failed"); + guarantee(next->is_oop(), "next field should be an oop"); + guarantee(next->is_instance(), "next field should be an instance"); + guarantee(InstanceKlass::cast(next->klass())->is_reference_instance_klass(), "next field verify failed"); } } diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 30bdc14cd2a..273c6c062bc 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -348,7 +348,7 @@ GrowableArray* Klass::compute_secondary_supers(int num_extra_slots) { InstanceKlass* Klass::superklass() const { - assert(super() == NULL || super()->oop_is_instance(), "must be instance klass"); + assert(super() == NULL || super()->is_instance_klass(), "must be instance klass"); return _super == NULL ? NULL : InstanceKlass::cast(_super); } @@ -440,10 +440,9 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive } // Clean the implementors list and method data. - if (clean_alive_klasses && current->oop_is_instance()) { + if (clean_alive_klasses && current->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(current); - ik->clean_implementors_list(is_alive); - ik->clean_method_data(is_alive); + ik->clean_weak_instanceklass_links(is_alive); } } } @@ -558,9 +557,11 @@ Klass* Klass::array_klass_impl(bool or_null, TRAPS) { oop Klass::class_loader() const { return class_loader_data()->class_loader(); } +// In product mode, this function doesn't have virtual function calls so +// there might be some performance advantage to handling InstanceKlass here. const char* Klass::external_name() const { - if (oop_is_instance()) { - InstanceKlass* ik = (InstanceKlass*) this; + if (is_instance_klass()) { + const InstanceKlass* ik = static_cast(this); if (ik->is_anonymous()) { intptr_t hash = 0; if (ik->java_mirror() != NULL) { @@ -688,19 +689,13 @@ void Klass::oop_verify_on(oop obj, outputStream* st) { #ifndef PRODUCT bool Klass::verify_vtable_index(int i) { - if (oop_is_instance()) { - int limit = ((InstanceKlass*)this)->vtable_length()/vtableEntry::size(); - assert(i >= 0 && i < limit, "index %d out of bounds %d", i, limit); - } else { - assert(oop_is_array(), "Must be"); - int limit = ((ArrayKlass*)this)->vtable_length()/vtableEntry::size(); - assert(i >= 0 && i < limit, "index %d out of bounds %d", i, limit); - } + int limit = vtable_length()/vtableEntry::size(); + assert(i >= 0 && i < limit, "index %d out of bounds %d", i, limit); return true; } bool Klass::verify_itable_index(int i) { - assert(oop_is_instance(), ""); + assert(is_instance_klass(), ""); int method_count = klassItable::method_count_for_interface(this); assert(i >= 0 && i < method_count, "index out of bounds"); return true; @@ -716,11 +711,11 @@ class TestKlass { public: static void test_oop_is_instanceClassLoader() { Klass* klass = SystemDictionary::ClassLoader_klass(); - guarantee(klass->oop_is_instance(), "assert"); + guarantee(klass->is_instance_klass(), "assert"); guarantee(InstanceKlass::cast(klass)->is_class_loader_instance_klass(), "test failed"); klass = SystemDictionary::String_klass(); - guarantee(!klass->oop_is_instance() || + guarantee(!klass->is_instance_klass() || !InstanceKlass::cast(klass)->is_class_loader_instance_klass(), "test failed"); } @@ -730,4 +725,4 @@ void TestKlass_test() { TestKlass::test_oop_is_instanceClassLoader(); } -#endif +#endif // PRODUCT diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index aa8aabb61fa..a7ddf019063 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -373,8 +373,8 @@ protected: #endif // vtables - virtual klassVtable* vtable() const { return NULL; } - virtual int vtable_length() const { return 0; } + virtual klassVtable* vtable() const = 0; + virtual int vtable_length() const = 0; // subclass check bool is_subclass_of(const Klass* k) const; @@ -474,11 +474,13 @@ protected: virtual const char* signature_name() const; // type testing operations +#ifdef ASSERT protected: - virtual bool oop_is_instance_slow() const { return false; } - virtual bool oop_is_array_slow() const { return false; } - virtual bool oop_is_objArray_slow() const { return false; } - virtual bool oop_is_typeArray_slow() const { return false; } + virtual bool is_instance_klass_slow() const { return false; } + virtual bool is_array_klass_slow() const { return false; } + virtual bool is_objArray_klass_slow() const { return false; } + virtual bool is_typeArray_klass_slow() const { return false; } +#endif // ASSERT public: // Fast non-virtual versions @@ -492,18 +494,18 @@ protected: } public: #endif - inline bool oop_is_instance() const { return assert_same_query( - layout_helper_is_instance(layout_helper()), - oop_is_instance_slow()); } - inline bool oop_is_array() const { return assert_same_query( + inline bool is_instance_klass() const { return assert_same_query( + layout_helper_is_instance(layout_helper()), + is_instance_klass_slow()); } + inline bool is_array_klass() const { return assert_same_query( layout_helper_is_array(layout_helper()), - oop_is_array_slow()); } - inline bool oop_is_objArray() const { return assert_same_query( + is_array_klass_slow()); } + inline bool is_objArray_klass() const { return assert_same_query( layout_helper_is_objArray(layout_helper()), - oop_is_objArray_slow()); } - inline bool oop_is_typeArray() const { return assert_same_query( + is_objArray_klass_slow()); } + inline bool is_typeArray_klass() const { return assert_same_query( layout_helper_is_typeArray(layout_helper()), - oop_is_typeArray_slow()); } + is_typeArray_klass_slow()); } #undef assert_same_query // Access flags diff --git a/hotspot/src/share/vm/oops/klass.inline.hpp b/hotspot/src/share/vm/oops/klass.inline.hpp index 5c820f574c1..5609980579f 100644 --- a/hotspot/src/share/vm/oops/klass.inline.hpp +++ b/hotspot/src/share/vm/oops/klass.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ #include "oops/markOop.hpp" inline void Klass::set_prototype_header(markOop header) { - assert(!header->has_bias_pattern() || oop_is_instance(), "biased locking currently only supported for Java instances"); + assert(!header->has_bias_pattern() || is_instance_klass(), "biased locking currently only supported for Java instances"); _prototype_header = header; } diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index 9872b3fca55..7f6ae730c2e 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -39,9 +39,7 @@ #include "utilities/copy.hpp" inline InstanceKlass* klassVtable::ik() const { - Klass* k = _klass(); - assert(k->oop_is_instance(), "not an InstanceKlass"); - return (InstanceKlass*)k; + return InstanceKlass::cast(_klass()); } @@ -66,8 +64,7 @@ void klassVtable::compute_vtable_size_and_num_mirandas( int vtable_length = 0; // start off with super's vtable length - InstanceKlass* sk = (InstanceKlass*)super; - vtable_length = super == NULL ? 0 : sk->vtable_length(); + vtable_length = super == NULL ? 0 : super->vtable_length(); // go thru each method in the methods table to see if it needs a new entry int len = methods->length(); @@ -131,10 +128,7 @@ int klassVtable::initialize_from_super(KlassHandle super) { return 0; } else { // copy methods from superKlass - // can't inherit from array class, so must be InstanceKlass - assert(super->oop_is_instance(), "must be instance klass"); - InstanceKlass* sk = (InstanceKlass*)super(); - klassVtable* superVtable = sk->vtable(); + klassVtable* superVtable = super->vtable(); assert(superVtable->length() <= _length, "vtable too short"); #ifdef ASSERT superVtable->verify(tty, true); @@ -143,7 +137,7 @@ int klassVtable::initialize_from_super(KlassHandle super) { #ifndef PRODUCT if (PrintVtables && Verbose) { ResourceMark rm; - tty->print_cr("copy vtable from %s to %s size %d", sk->internal_name(), klass()->internal_name(), _length); + tty->print_cr("copy vtable from %s to %s size %d", super->internal_name(), klass()->internal_name(), _length); } #endif return superVtable->length(); @@ -158,7 +152,7 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { KlassHandle super (THREAD, klass()->java_super()); int nofNewEntries = 0; - if (PrintVtables && !klass()->oop_is_array()) { + if (PrintVtables && !klass()->is_array_klass()) { ResourceMark rm(THREAD); tty->print_cr("Initializing: %s", _klass->name()->as_C_string()); } @@ -176,10 +170,10 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { } int super_vtable_len = initialize_from_super(super); - if (klass()->oop_is_array()) { + if (klass()->is_array_klass()) { assert(super_vtable_len == _length, "arrays shouldn't introduce new methods"); } else { - assert(_klass->oop_is_instance(), "must be InstanceKlass"); + assert(_klass->is_instance_klass(), "must be InstanceKlass"); Array* methods = ik()->methods(); int len = methods->length(); @@ -303,7 +297,7 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper break; } // if no override found yet, continue to search up - superk = InstanceKlass::cast(superk->super()); + superk = superk->super() == NULL ? NULL : InstanceKlass::cast(superk->super()); } return superk; @@ -318,7 +312,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar bool checkconstraints, TRAPS) { ResourceMark rm; bool allocate_new = true; - assert(klass->oop_is_instance(), "must be InstanceKlass"); + assert(klass->is_instance_klass(), "must be InstanceKlass"); Array* def_vtable_indices = NULL; bool is_default = false; @@ -761,15 +755,14 @@ bool klassVtable::is_miranda(Method* m, Array* class_methods, return false; } - InstanceKlass* cursuper; - // Iterate on all superclasses, which should have instanceKlasses + // Iterate on all superclasses, which should be InstanceKlasses. // Note that we explicitly look for overpasses at each level. // Overpasses may or may not exist for supers for pass 1, // they should have been created for pass 2 and later. - for (cursuper = InstanceKlass::cast(super); cursuper != NULL; cursuper = (InstanceKlass*)cursuper->super()) + for (Klass* cursuper = super; cursuper != NULL; cursuper = cursuper->super()) { - if (cursuper->find_local_method(name, signature, + if (InstanceKlass::cast(cursuper)->find_local_method(name, signature, Klass::find_overpass, Klass::skip_static, Klass::skip_private) != NULL) { return false; } @@ -1117,7 +1110,7 @@ int klassItable::assign_itable_indices_for_interface(Klass* klass) { } int klassItable::method_count_for_interface(Klass* interf) { - assert(interf->oop_is_instance(), "must be"); + assert(interf->is_instance_klass(), "must be"); assert(interf->is_interface(), "must be"); Array* methods = InstanceKlass::cast(interf)->methods(); int nof_methods = methods->length(); @@ -1534,11 +1527,11 @@ class VtableStats : AllStatic { klassVtable* vt = kl->vtable(); if (vt == NULL) return; no_klasses++; - if (kl->oop_is_instance()) { + if (kl->is_instance_klass()) { no_instance_klasses++; kl->array_klasses_do(do_class); } - if (kl->oop_is_array()) { + if (kl->is_array_klass()) { no_array_klasses++; sum_of_array_vtable_len += vt->length(); } diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 192769f7226..1c175b06f98 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -299,10 +299,7 @@ int Method::size(bool is_native) { Symbol* Method::klass_name() const { - Klass* k = method_holder(); - assert(k->is_klass(), "must be klass"); - InstanceKlass* ik = (InstanceKlass*) k; - return ik->name(); + return method_holder()->name(); } @@ -366,7 +363,7 @@ void Method::print_invocation_count() { // Build a MethodData* object to hold information about this method // collected in the interpreter. -void Method::build_interpreter_method_data(methodHandle method, TRAPS) { +void Method::build_interpreter_method_data(const methodHandle& method, TRAPS) { // Do not profile the method if metaspace has hit an OOM previously // allocating profiling data. Callers clear pending exception so don't // add one here. @@ -897,7 +894,7 @@ void Method::unlink_method() { // Called when the method_holder is getting linked. Setup entrypoints so the method // is ready to be called from interpreter, compiler, and vtables. -void Method::link_method(methodHandle h_method, TRAPS) { +void Method::link_method(const methodHandle& h_method, TRAPS) { // If the code cache is full, we may reenter this function for the // leftover methods that weren't linked. if (_i2i_entry != NULL) return; @@ -1178,7 +1175,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, Klass* Method::check_non_bcp_klass(Klass* klass) { if (klass != NULL && klass->class_loader() != NULL) { - if (klass->oop_is_objArray()) + if (klass->is_objArray_klass()) klass = ObjArrayKlass::cast(klass)->bottom_klass(); return klass; } @@ -1305,6 +1302,73 @@ vmSymbols::SID Method::klass_id_for_intrinsics(Klass* holder) { return vmSymbols::find_sid(klass_name); } +static bool is_unsafe_alias(vmSymbols::SID name_id) { + // All 70 intrinsic candidate methods from sun.misc.Unsafe in 1.8. + // Some have the same method name but different signature, e.g. + // getByte(long), getByte(Object,long) + switch (name_id) { + case vmSymbols::VM_SYMBOL_ENUM_NAME(allocateInstance_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(copyMemory_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(loadFence_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(storeFence_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(fullFence_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getObject_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getBoolean_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getByte_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getShort_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getChar_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getInt_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getLong_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloat_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getDouble_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putObject_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putBoolean_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putByte_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putShort_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putChar_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putInt_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putLong_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloat_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putDouble_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getObjectVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getBooleanVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getByteVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getShortVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getCharVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getIntVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getLongVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloatVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getDoubleVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putObjectVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putBooleanVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putByteVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putShortVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putCharVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putIntVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putLongVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloatVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putDoubleVolatile_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getAddress_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putAddress_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapObject_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapLong_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapInt_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedObject_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedLong_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedInt_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddInt_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddLong_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetInt_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetLong_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetObject_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(park_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(unpark_name): + return true; + } + + return false; +} + void Method::init_intrinsic_id() { assert(_intrinsic_id == vmIntrinsics::_none, "do this just once"); const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte)); @@ -1357,6 +1421,14 @@ void Method::init_intrinsic_id() { if (is_static() != MethodHandles::is_signature_polymorphic_static(id)) id = vmIntrinsics::_none; break; + + case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Unsafe): + // Map sun.misc.Unsafe to jdk.internal.misc.Unsafe + if (!is_unsafe_alias(name_id)) break; + // pretend it is the corresponding method in the internal Unsafe class: + klass_id = vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_misc_Unsafe); + id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); + break; } if (id != vmIntrinsics::_none) { diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index f1a2e916f7d..b0cd50ec0c6 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -393,7 +393,7 @@ class Method : public Metadata { bool was_executed_more_than(int n); bool was_never_executed() { return !was_executed_more_than(0); } - static void build_interpreter_method_data(methodHandle method, TRAPS); + static void build_interpreter_method_data(const methodHandle& method, TRAPS); static MethodCounters* build_method_counters(Method* m, TRAPS); @@ -435,7 +435,7 @@ class Method : public Metadata { address get_c2i_unverified_entry(); AdapterHandlerEntry* adapter() { return _adapter; } // setup entry points - void link_method(methodHandle method, TRAPS); + void link_method(const methodHandle& method, TRAPS); // clear entry points. Used by sharing code void unlink_method(); diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index c74a611ffe1..f460028393f 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -708,7 +708,7 @@ void SpeculativeTrapData::print_data_on(outputStream* st, const char* extra) con // A MethodData* holds information which has been collected about // a method. -MethodData* MethodData::allocate(ClassLoaderData* loader_data, methodHandle method, TRAPS) { +MethodData* MethodData::allocate(ClassLoaderData* loader_data, const methodHandle& method, TRAPS) { int size = MethodData::compute_allocation_size_in_words(method); return new (loader_data, size, false, MetaspaceObj::MethodDataType, THREAD) @@ -898,7 +898,7 @@ int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool // Compute the size of the MethodData* necessary to store // profiling information about a given method. Size is in bytes. -int MethodData::compute_allocation_size_in_bytes(methodHandle method) { +int MethodData::compute_allocation_size_in_bytes(const methodHandle& method) { int data_size = 0; BytecodeStream stream(method); Bytecodes::Code c; @@ -931,7 +931,7 @@ int MethodData::compute_allocation_size_in_bytes(methodHandle method) { // Compute the size of the MethodData* necessary to store // profiling information about a given method. Size is in words -int MethodData::compute_allocation_size_in_words(methodHandle method) { +int MethodData::compute_allocation_size_in_words(const methodHandle& method) { int byte_size = compute_allocation_size_in_bytes(method); int word_size = align_size_up(byte_size, BytesPerWord) / BytesPerWord; return align_object_size(word_size); @@ -1102,7 +1102,9 @@ ProfileData* DataLayout::data_in() { return new VirtualCallTypeData(this); case DataLayout::parameters_type_data_tag: return new ParametersTypeData(this); - }; + case DataLayout::speculative_trap_data_tag: + return new SpeculativeTrapData(this); + } } // Iteration over data. @@ -1129,7 +1131,7 @@ void MethodData::post_initialize(BytecodeStream* stream) { } // Initialize the MethodData* corresponding to a given method. -MethodData::MethodData(methodHandle method, int size, TRAPS) +MethodData::MethodData(const methodHandle& method, int size, TRAPS) : _extra_data_lock(Monitor::leaf, "MDO extra data lock"), _parameters_type_data_di(parameters_uninitialized) { // Set the method back-pointer. @@ -1513,7 +1515,7 @@ void MethodData::verify_data_on(outputStream* st) { // not yet implemented. } -bool MethodData::profile_jsr292(methodHandle m, int bci) { +bool MethodData::profile_jsr292(const methodHandle& m, int bci) { if (m->is_compiled_lambda_form()) { return true; } @@ -1538,7 +1540,7 @@ bool MethodData::profile_all_arguments() { return profile_arguments_flag() == type_profile_all; } -bool MethodData::profile_arguments_for_invoke(methodHandle m, int bci) { +bool MethodData::profile_arguments_for_invoke(const methodHandle& m, int bci) { if (!profile_arguments()) { return false; } @@ -1567,7 +1569,7 @@ bool MethodData::profile_all_return() { return profile_return_flag() == type_profile_all; } -bool MethodData::profile_return_for_invoke(methodHandle m, int bci) { +bool MethodData::profile_return_for_invoke(const methodHandle& m, int bci) { if (!profile_return()) { return false; } @@ -1596,7 +1598,7 @@ bool MethodData::profile_all_parameters() { return profile_parameters_flag() == type_profile_all; } -bool MethodData::profile_parameters_for_method(methodHandle m) { +bool MethodData::profile_parameters_for_method(const methodHandle& m) { if (!profile_parameters()) { return false; } diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index ac58123f8b7..14afeccea57 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, 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 @@ -535,6 +535,7 @@ public: // // A BitData holds a flag or two in its header. class BitData : public ProfileData { + friend class VMStructs; protected: enum { // null_seen: @@ -603,6 +604,7 @@ public: // // A CounterData corresponds to a simple counter. class CounterData : public BitData { + friend class VMStructs; protected: enum { count_off, @@ -667,6 +669,7 @@ public: // plus a data displacement, used for realigning the data pointer to // the corresponding target bci. class JumpData : public ProfileData { + friend class VMStructs; protected: enum { taken_off_set, @@ -1173,6 +1176,7 @@ public: // that the check is reached, and a series of (Klass*, count) pairs // which are used to store a type profile for the receiver of the check. class ReceiverTypeData : public CounterData { + friend class VMStructs; protected: enum { #if INCLUDE_JVMCI @@ -1678,6 +1682,7 @@ public: // It consists of taken and not_taken counts as well as a data displacement // for the taken case. class BranchData : public JumpData { + friend class VMStructs; protected: enum { not_taken_off_set = jump_cell_count, @@ -1754,6 +1759,7 @@ public: // not have a statically known size. It consists of an array length // and an array start. class ArrayData : public ProfileData { + friend class VMStructs; protected: friend class DataLayout; @@ -1831,6 +1837,7 @@ public: // of (count, displacement) pairs, which count the number of times each // case was taken and specify the data displacment for each branch target. class MultiBranchData : public ArrayData { + friend class VMStructs; protected: enum { default_count_off_set, @@ -2145,9 +2152,9 @@ private: Mutex _extra_data_lock; - MethodData(methodHandle method, int size, TRAPS); + MethodData(const methodHandle& method, int size, TRAPS); public: - static MethodData* allocate(ClassLoaderData* loader_data, methodHandle method, TRAPS); + static MethodData* allocate(ClassLoaderData* loader_data, const methodHandle& method, TRAPS); MethodData() : _extra_data_lock(Monitor::leaf, "MDO extra data lock") {}; // For ciMethodData bool is_methodData() const volatile { return true; } @@ -2283,13 +2290,13 @@ private: type_profile_all = 2 }; - static bool profile_jsr292(methodHandle m, int bci); + static bool profile_jsr292(const methodHandle& m, int bci); static int profile_arguments_flag(); static bool profile_all_arguments(); - static bool profile_arguments_for_invoke(methodHandle m, int bci); + static bool profile_arguments_for_invoke(const methodHandle& m, int bci); static int profile_return_flag(); static bool profile_all_return(); - static bool profile_return_for_invoke(methodHandle m, int bci); + static bool profile_return_for_invoke(const methodHandle& m, int bci); static int profile_parameters_flag(); static bool profile_parameters_jsr292_only(); static bool profile_all_parameters(); @@ -2304,8 +2311,8 @@ public: } // Compute the size of a MethodData* before it is created. - static int compute_allocation_size_in_bytes(methodHandle method); - static int compute_allocation_size_in_words(methodHandle method); + static int compute_allocation_size_in_bytes(const methodHandle& method); + static int compute_allocation_size_in_words(const methodHandle& method); static int compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps); // Determine if a given bytecode can have profile information. @@ -2589,7 +2596,7 @@ public: void verify_on(outputStream* st); void verify_data_on(outputStream* st); - static bool profile_parameters_for_method(methodHandle m); + static bool profile_parameters_for_method(const methodHandle& m); static bool profile_arguments(); static bool profile_arguments_jsr292_only(); static bool profile_return(); diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index eb7a84e192a..bd696d5cc0f 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -102,7 +102,7 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, // Create type name for klass. Symbol* name = NULL; - if (!element_klass->oop_is_instance() || + if (!element_klass->is_instance_klass() || (name = InstanceKlass::cast(element_klass())->array_name()) == NULL) { ResourceMark rm(THREAD); @@ -111,17 +111,17 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, char *new_str = NEW_RESOURCE_ARRAY(char, len + 4); int idx = 0; new_str[idx++] = '['; - if (element_klass->oop_is_instance()) { // it could be an array or simple type + if (element_klass->is_instance_klass()) { // it could be an array or simple type new_str[idx++] = 'L'; } memcpy(&new_str[idx], name_str, len * sizeof(char)); idx += len; - if (element_klass->oop_is_instance()) { + if (element_klass->is_instance_klass()) { new_str[idx++] = ';'; } new_str[idx++] = '\0'; name = SymbolTable::new_permanent_symbol(new_str, CHECK_0); - if (element_klass->oop_is_instance()) { + if (element_klass->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(element_klass()); ik->set_array_name(name); } @@ -150,18 +150,18 @@ ObjArrayKlass::ObjArrayKlass(int n, KlassHandle element_klass, Symbol* name) : A name->decrement_refcount(); Klass* bk; - if (element_klass->oop_is_objArray()) { + if (element_klass->is_objArray_klass()) { bk = ObjArrayKlass::cast(element_klass())->bottom_klass(); } else { bk = element_klass(); } - assert(bk != NULL && (bk->oop_is_instance() || bk->oop_is_typeArray()), "invalid bottom klass"); + assert(bk != NULL && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass"); this->set_bottom_klass(bk); this->set_class_loader_data(bk->class_loader_data()); this->set_layout_helper(array_layout_helper(T_OBJECT)); - assert(this->oop_is_array(), "sanity"); - assert(this->oop_is_objArray(), "sanity"); + assert(this->is_array_klass(), "sanity"); + assert(this->is_objArray_klass(), "sanity"); } int ObjArrayKlass::oop_size(oop obj) const { @@ -336,7 +336,7 @@ Klass* ObjArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { ak->set_lower_dimension(this); OrderAccess::storestore(); set_higher_dimension(ak); - assert(ak->oop_is_objArray(), "incorrect initialization of ObjArrayKlass"); + assert(ak->is_objArray_klass(), "incorrect initialization of ObjArrayKlass"); } } } else { @@ -386,7 +386,7 @@ GrowableArray* ObjArrayKlass::compute_secondary_supers(int num_extra_slo } bool ObjArrayKlass::compute_is_subtype_of(Klass* k) { - if (!k->oop_is_objArray()) + if (!k->is_objArray_klass()) return ArrayKlass::compute_is_subtype_of(k); ObjArrayKlass* oak = ObjArrayKlass::cast(k); @@ -484,7 +484,7 @@ void ObjArrayKlass::verify_on(outputStream* st) { guarantee(element_klass()->is_klass(), "should be klass"); guarantee(bottom_klass()->is_klass(), "should be klass"); Klass* bk = bottom_klass(); - guarantee(bk->oop_is_instance() || bk->oop_is_typeArray(), "invalid bottom klass"); + guarantee(bk->is_instance_klass() || bk->is_typeArray_klass(), "invalid bottom klass"); } void ObjArrayKlass::oop_verify_on(oop obj, outputStream* st) { diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index fa4a37b7556..d888fb7228a 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -60,7 +60,7 @@ class ObjArrayKlass : public ArrayKlass { bool can_be_primary_super_slow() const; GrowableArray* compute_secondary_supers(int num_extra_slots); bool compute_is_subtype_of(Klass* k); - bool oop_is_objArray_slow() const { return true; } + DEBUG_ONLY(bool is_objArray_klass_slow() const { return true; }) int oop_size(oop obj) const; // Allocation @@ -91,8 +91,8 @@ class ObjArrayKlass : public ArrayKlass { public: // Casting from Klass* static ObjArrayKlass* cast(Klass* k) { - assert(k->oop_is_objArray(), "cast to ObjArrayKlass"); - return (ObjArrayKlass*) k; + assert(k->is_objArray_klass(), "cast to ObjArrayKlass"); + return static_cast(k); } // Sizing diff --git a/hotspot/src/share/vm/oops/oop.cpp b/hotspot/src/share/vm/oops/oop.cpp index e801ae30229..18d1f227b48 100644 --- a/hotspot/src/share/vm/oops/oop.cpp +++ b/hotspot/src/share/vm/oops/oop.cpp @@ -129,9 +129,6 @@ void VerifyOopClosure::do_oop(narrowOop* p) { VerifyOopClosure::do_oop_work(p); // type test operations that doesn't require inclusion of oop.inline.hpp. bool oopDesc::is_instance_noinline() const { return is_instance(); } -bool oopDesc::is_instanceMirror_noinline() const { return is_instanceMirror(); } -bool oopDesc::is_instanceClassLoader_noline() const { return is_instanceClassLoader(); } -bool oopDesc::is_instanceRef_noline() const { return is_instanceRef(); } bool oopDesc::is_array_noinline() const { return is_array(); } bool oopDesc::is_objArray_noinline() const { return is_objArray(); } bool oopDesc::is_typeArray_noinline() const { return is_typeArray(); } diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index ed969cf6f7f..b096f3f45c5 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -110,18 +110,12 @@ class oopDesc { // type test operations (inlined in oop.inline.hpp) bool is_instance() const; - bool is_instanceMirror() const; - bool is_instanceClassLoader() const; - bool is_instanceRef() const; bool is_array() const; bool is_objArray() const; bool is_typeArray() const; // type test operations that don't require inclusion of oop.inline.hpp. bool is_instance_noinline() const; - bool is_instanceMirror_noinline() const; - bool is_instanceClassLoader_noline() const; - bool is_instanceRef_noline() const; bool is_array_noinline() const; bool is_objArray_noinline() const; bool is_typeArray_noinline() const; diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 4ab957dbd26..bc480f49dea 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -127,27 +127,12 @@ inline void oopDesc::init_mark() { set_mark(markOopDesc::proto inline bool oopDesc::is_a(Klass* k) const { return klass()->is_subtype_of(k); } inline bool oopDesc::is_instance() const { - return klass()->oop_is_instance(); + return klass()->is_instance_klass(); } -inline bool oopDesc::is_instanceClassLoader() const { - Klass* k = klass(); - return k->oop_is_instance() && InstanceKlass::cast(k)->is_class_loader_instance_klass(); -} - -inline bool oopDesc::is_instanceMirror() const { - Klass* k = klass(); - return k->oop_is_instance() && InstanceKlass::cast(k)->is_mirror_instance_klass(); -} - -inline bool oopDesc::is_instanceRef() const { - Klass* k = klass(); - return k->oop_is_instance() && InstanceKlass::cast(k)->is_reference_instance_klass(); -} - -inline bool oopDesc::is_array() const { return klass()->oop_is_array(); } -inline bool oopDesc::is_objArray() const { return klass()->oop_is_objArray(); } -inline bool oopDesc::is_typeArray() const { return klass()->oop_is_typeArray(); } +inline bool oopDesc::is_array() const { return klass()->is_array_klass(); } +inline bool oopDesc::is_objArray() const { return klass()->is_objArray_klass(); } +inline bool oopDesc::is_typeArray() const { return klass()->is_typeArray_klass(); } inline void* oopDesc::field_base(int offset) const { return (void*)&((char*)this)[offset]; } @@ -724,7 +709,7 @@ inline void oopDesc::pc_follow_contents(ParCompactionManager* cm) { inline void oopDesc::pc_update_contents() { Klass* k = klass(); - if (!k->oop_is_typeArray()) { + if (!k->is_typeArray_klass()) { // It might contain oops beyond the header, so take the virtual call. k->oop_pc_update_pointers(this); } @@ -733,7 +718,7 @@ inline void oopDesc::pc_update_contents() { inline void oopDesc::ps_push_contents(PSPromotionManager* pm) { Klass* k = klass(); - if (!k->oop_is_typeArray()) { + if (!k->is_typeArray_klass()) { // It might contain oops beyond the header, so take the virtual call. k->oop_ps_push_contents(this, pm); } diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlass.cpp index 8b1453ff6c6..2e76bc4d96a 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp @@ -43,7 +43,7 @@ #include "utilities/macros.hpp" bool TypeArrayKlass::compute_is_subtype_of(Klass* k) { - if (!k->oop_is_typeArray()) { + if (!k->is_typeArray_klass()) { return ArrayKlass::compute_is_subtype_of(k); } @@ -86,8 +86,8 @@ TypeArrayKlass* TypeArrayKlass::allocate(ClassLoaderData* loader_data, BasicType TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name) { set_layout_helper(array_layout_helper(type)); - assert(oop_is_array(), "sanity"); - assert(oop_is_typeArray(), "sanity"); + assert(is_array_klass(), "sanity"); + assert(is_typeArray_klass(), "sanity"); set_max_length(arrayOopDesc::max_array_length(type)); assert(size() >= TypeArrayKlass::header_size(), "bad size"); @@ -181,7 +181,7 @@ Klass* TypeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { h_ak->set_lower_dimension(this); OrderAccess::storestore(); set_higher_dimension(h_ak); - assert(h_ak->oop_is_objArray(), "incorrect initialization of ObjArrayKlass"); + assert(h_ak->is_objArray_klass(), "incorrect initialization of ObjArrayKlass"); } } } else { diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.hpp b/hotspot/src/share/vm/oops/typeArrayKlass.hpp index 1ef2775b2fc..f794b60326b 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/typeArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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,7 +47,7 @@ class TypeArrayKlass : public ArrayKlass { void set_max_length(jint m) { _max_length = m; } // testers - bool oop_is_typeArray_slow() const { return true; } + DEBUG_ONLY(bool is_typeArray_klass_slow() const { return true; }) // klass allocation static TypeArrayKlass* create_klass(BasicType type, const char* name_str, @@ -122,8 +122,8 @@ class TypeArrayKlass : public ArrayKlass { public: // Casting from Klass* static TypeArrayKlass* cast(Klass* k) { - assert(k->oop_is_typeArray(), "cast to TypeArrayKlass"); - return (TypeArrayKlass*) k; + assert(k->is_typeArray_klass(), "cast to TypeArrayKlass"); + return static_cast(k); } // Naming diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp index 7d61e8946a2..57036c2c0c8 100644 --- a/hotspot/src/share/vm/oops/typeArrayOop.hpp +++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp @@ -48,47 +48,47 @@ class typeArrayOopDesc : public arrayOopDesc { public: jbyte* byte_at_addr(int which) const { - assert(is_within_bounds(which), "index out of bounds"); + assert(is_within_bounds(which), "index %d out of bounds %d", which, length()); return &byte_base()[which]; } jboolean* bool_at_addr(int which) const { - assert(is_within_bounds(which), "index out of bounds"); + assert(is_within_bounds(which), "index %d out of bounds %d", which, length()); return &bool_base()[which]; } jchar* char_at_addr(int which) const { - assert(is_within_bounds(which), "index out of bounds"); + assert(is_within_bounds(which), "index %d out of bounds %d", which, length()); return &char_base()[which]; } jint* int_at_addr(int which) const { - assert(is_within_bounds(which), "index out of bounds"); + assert(is_within_bounds(which), "index %d out of bounds %d", which, length()); return &int_base()[which]; } jshort* short_at_addr(int which) const { - assert(is_within_bounds(which), "index out of bounds"); + assert(is_within_bounds(which), "index %d out of bounds %d", which, length()); return &short_base()[which]; } jushort* ushort_at_addr(int which) const { // for field descriptor arrays - assert(is_within_bounds(which), "index out of bounds"); + assert(is_within_bounds(which), "index %d out of bounds %d", which, length()); return (jushort*) &short_base()[which]; } jlong* long_at_addr(int which) const { - assert(is_within_bounds(which), "index out of bounds"); + assert(is_within_bounds(which), "index %d out of bounds %d", which, length()); return &long_base()[which]; } jfloat* float_at_addr(int which) const { - assert(is_within_bounds(which), "index out of bounds"); + assert(is_within_bounds(which), "index %d out of bounds %d", which, length()); return &float_base()[which]; } jdouble* double_at_addr(int which) const { - assert(is_within_bounds(which), "index out of bounds"); + assert(is_within_bounds(which), "index %d out of bounds %d", which, length()); return &double_base()[which]; } diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index 9dfcd5c79e3..60f1f200248 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -158,7 +158,7 @@ void C2Compiler::print_timers() { Compile::print_timers(); } -bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) { +bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virtual) { vmIntrinsics::ID id = method->intrinsic_id(); assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); @@ -181,12 +181,25 @@ bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) { } switch (id) { - case vmIntrinsics::_compareTo: + case vmIntrinsics::_compressStringC: + case vmIntrinsics::_compressStringB: + if (!Matcher::has_match_rule(Op_StrCompressedCopy)) return false; + break; + case vmIntrinsics::_inflateStringC: + case vmIntrinsics::_inflateStringB: + if (!Matcher::has_match_rule(Op_StrInflatedCopy)) return false; + break; + case vmIntrinsics::_compareToL: + case vmIntrinsics::_compareToU: + case vmIntrinsics::_compareToLU: + case vmIntrinsics::_compareToUL: if (!Matcher::match_rule_supported(Op_StrComp)) return false; break; - case vmIntrinsics::_equals: + case vmIntrinsics::_equalsL: + case vmIntrinsics::_equalsU: if (!Matcher::match_rule_supported(Op_StrEquals)) return false; break; + case vmIntrinsics::_equalsB: case vmIntrinsics::_equalsC: if (!Matcher::match_rule_supported(Op_AryEq)) return false; break; @@ -194,8 +207,12 @@ bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) { if (StubRoutines::unsafe_arraycopy() == NULL) return false; break; case vmIntrinsics::_encodeISOArray: + case vmIntrinsics::_encodeByteISOArray: if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return false; break; + case vmIntrinsics::_hasNegatives: + if (!Matcher::match_rule_supported(Op_HasNegatives)) return false; + break; case vmIntrinsics::_bitCount_i: if (!Matcher::match_rule_supported(Op_PopCountI)) return false; break; @@ -302,7 +319,17 @@ bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) { case vmIntrinsics::_min: case vmIntrinsics::_max: case vmIntrinsics::_arraycopy: - case vmIntrinsics::_indexOf: + case vmIntrinsics::_indexOfL: + case vmIntrinsics::_indexOfU: + case vmIntrinsics::_indexOfUL: + case vmIntrinsics::_indexOfIL: + case vmIntrinsics::_indexOfIU: + case vmIntrinsics::_indexOfIUL: + case vmIntrinsics::_indexOfU_char: + case vmIntrinsics::_toBytesStringU: + case vmIntrinsics::_getCharsStringU: + case vmIntrinsics::_getCharStringU: + case vmIntrinsics::_putCharStringU: case vmIntrinsics::_getObject: case vmIntrinsics::_getBoolean: case vmIntrinsics::_getByte: diff --git a/hotspot/src/share/vm/opto/c2compiler.hpp b/hotspot/src/share/vm/opto/c2compiler.hpp index 016b4908e33..9df31b4f712 100644 --- a/hotspot/src/share/vm/opto/c2compiler.hpp +++ b/hotspot/src/share/vm/opto/c2compiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -57,13 +57,13 @@ public: // possible for only a limited set of available intrinsics whereas // a non-virtual dispatch is possible for all available intrinsics.) // Return false otherwise. - virtual bool is_intrinsic_supported(methodHandle method) { + virtual bool is_intrinsic_supported(const methodHandle& method) { return is_intrinsic_supported(method, false); } // Check if the compiler supports an intrinsic for 'method' given the // the dispatch mode specified by the 'is_virtual' parameter. - virtual bool is_intrinsic_supported(methodHandle method, bool is_virtual); + virtual bool is_intrinsic_supported(const methodHandle& method, bool is_virtual); // Initial size of the code buffer (may be increased at runtime) static int initial_code_buffer_size(); diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 7e569551c79..ff86ad4750d 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -671,7 +671,7 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms) { &exact_receiver); SafePointNode* slow_map = NULL; - JVMState* slow_jvms; + JVMState* slow_jvms = NULL; { PreserveJVMState pjvms(&kit); kit.set_control(slow_ctl); if (!kit.stopped()) { diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index 4464d6a8b6a..754c8f6a08f 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -136,6 +136,7 @@ macro(FastLock) macro(FastUnlock) macro(Goto) macro(Halt) +macro(HasNegatives) macro(If) macro(IfFalse) macro(IfTrue) @@ -246,8 +247,11 @@ macro(StoreP) macro(StoreN) macro(StoreNKlass) macro(StrComp) +macro(StrCompressedCopy) macro(StrEquals) macro(StrIndexOf) +macro(StrIndexOfChar) +macro(StrInflatedCopy) macro(SubD) macro(SubF) macro(SubI) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 94a97e3d5ae..032fe0a6f6f 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -3762,7 +3762,7 @@ void Compile::ConstantTable::emit(CodeBuffer& cb) { MacroAssembler _masm(&cb); for (int i = 0; i < _constants.length(); i++) { Constant con = _constants.at(i); - address constant_addr; + address constant_addr = NULL; switch (con.type()) { case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break; case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break; diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 511d8b1f046..27342ed12be 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -89,7 +89,7 @@ struct Final_Reshape_Counts; typedef unsigned int node_idx_t; class NodeCloneInfo { private: - uint64_t _idx_clone_orig; + uint64_t _idx_clone_orig; public: void set_idx(node_idx_t idx) { @@ -98,17 +98,17 @@ class NodeCloneInfo { node_idx_t idx() const { return (node_idx_t)(_idx_clone_orig & 0xFFFFFFFF); } void set_gen(int generation) { - uint64_t g = (uint64_t)generation << 32; + uint64_t g = (uint64_t)generation << 32; _idx_clone_orig = _idx_clone_orig & 0xFFFFFFFF | g; } int gen() const { return (int)(_idx_clone_orig >> 32); } - void set(uint64_t x) { _idx_clone_orig = x; } - void set(node_idx_t x, int g) { set_idx(x); set_gen(g); } + void set(uint64_t x) { _idx_clone_orig = x; } + void set(node_idx_t x, int g) { set_idx(x); set_gen(g); } uint64_t get() const { return _idx_clone_orig; } NodeCloneInfo(uint64_t idx_clone_orig) : _idx_clone_orig(idx_clone_orig) {} - NodeCloneInfo(node_idx_t x, int g) {set(x, g);} + NodeCloneInfo(node_idx_t x, int g) : _idx_clone_orig(0) { set(x, g); } void dump() const; }; diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index f1db509489d..fac8c4d67fe 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -560,9 +560,13 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de break; } case Op_AryEq: + case Op_HasNegatives: case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_StrIndexOfChar: + case Op_StrInflatedCopy: + case Op_StrCompressedCopy: case Op_EncodeISOArray: { add_local_var(n, PointsToNode::ArgEscape); delayed_worklist->push(n); // Process it later. @@ -743,11 +747,15 @@ void ConnectionGraph::add_final_edges(Node *n) { ELSE_FAIL("Op_StoreP"); } case Op_AryEq: + case Op_HasNegatives: case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_StrIndexOfChar: + case Op_StrInflatedCopy: + case Op_StrCompressedCopy: case Op_EncodeISOArray: { - // char[] arrays passed to string intrinsic do not escape but + // char[]/byte[] arrays passed to string intrinsic do not escape but // they are not scalar replaceable. Adjust escape state for them. // Start from in(2) edge since in(1) is memory edge. for (uint i = 2; i < n->req(); i++) { @@ -2722,17 +2730,34 @@ Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArra if (mem->is_LoadStore()) { adr = mem->in(MemNode::Address); } else { - assert(mem->Opcode() == Op_EncodeISOArray, "sanity"); + assert(mem->Opcode() == Op_EncodeISOArray || + mem->Opcode() == Op_StrCompressedCopy, "sanity"); adr = mem->in(3); // Memory edge corresponds to destination array } const Type *at = igvn->type(adr); if (at != Type::TOP) { - assert (at->isa_ptr() != NULL, "pointer type required."); + assert(at->isa_ptr() != NULL, "pointer type required."); int idx = C->get_alias_index(at->is_ptr()); - assert(idx != alias_idx, "Object is not scalar replaceable if a LoadStore node access its field"); - break; + if (idx == alias_idx) { + // Assert in debug mode + assert(false, "Object is not scalar replaceable if a LoadStore node accesses its field"); + break; // In product mode return SCMemProj node + } } result = mem->in(MemNode::Memory); + } else if (result->Opcode() == Op_StrInflatedCopy) { + Node* adr = result->in(3); // Memory edge corresponds to destination array + const Type *at = igvn->type(adr); + if (at != Type::TOP) { + assert(at->isa_ptr() != NULL, "pointer type required."); + int idx = C->get_alias_index(at->is_ptr()); + if (idx == alias_idx) { + // Assert in debug mode + assert(false, "Object is not scalar replaceable if a StrInflatedCopy node accesses its field"); + break; // In product mode return SCMemProj node + } + } + result = result->in(MemNode::Memory); } } if (result->is_Phi()) { @@ -3096,10 +3121,15 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, } } else { uint op = use->Opcode(); - if (!(op == Op_CmpP || op == Op_Conv2B || + if ((use->in(MemNode::Memory) == n) && + (op == Op_StrCompressedCopy || op == Op_StrInflatedCopy)) { + // They overwrite memory edge corresponding to destination array, + memnode_worklist.append_if_missing(use); + } else if (!(op == Op_CmpP || op == Op_Conv2B || op == Op_CastP2X || op == Op_StoreCM || - op == Op_FastLock || op == Op_AryEq || op == Op_StrComp || - op == Op_StrEquals || op == Op_StrIndexOf)) { + op == Op_FastLock || op == Op_AryEq || op == Op_StrComp || op == Op_HasNegatives || + op == Op_StrCompressedCopy || op == Op_StrInflatedCopy || + op == Op_StrEquals || op == Op_StrIndexOf || op == Op_StrIndexOfChar)) { n->dump(); use->dump(); assert(false, "EA: missing allocation reference path"); @@ -3161,7 +3191,8 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, n = n->as_MemBar()->proj_out(TypeFunc::Memory); if (n == NULL) continue; - } else if (n->Opcode() == Op_EncodeISOArray) { + } else if (n->Opcode() == Op_StrCompressedCopy || + n->Opcode() == Op_EncodeISOArray) { // get the memory projection n = n->find_out_with(Op_SCMemProj); assert(n->Opcode() == Op_SCMemProj, "memory projection required"); @@ -3216,11 +3247,16 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, } } else { uint op = use->Opcode(); - if (!(op == Op_StoreCM || + if ((use->in(MemNode::Memory) == n) && + (op == Op_StrCompressedCopy || op == Op_StrInflatedCopy)) { + // They overwrite memory edge corresponding to destination array, + memnode_worklist.append_if_missing(use); + } else if (!(op == Op_StoreCM || (op == Op_CallLeaf && use->as_CallLeaf()->_name != NULL && strcmp(use->as_CallLeaf()->_name, "g1_wb_pre") == 0) || - op == Op_AryEq || op == Op_StrComp || - op == Op_StrEquals || op == Op_StrIndexOf)) { + op == Op_AryEq || op == Op_StrComp || op == Op_HasNegatives || + op == Op_StrCompressedCopy || op == Op_StrInflatedCopy || + op == Op_StrEquals || op == Op_StrIndexOf || op == Op_StrIndexOfChar)) { n->dump(); use->dump(); assert(false, "EA: missing memory path"); diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index e73494b45e3..70c17ad8b1c 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -504,8 +504,12 @@ Block* PhaseCFG::insert_anti_dependences(Block* LCA, Node* load, bool verify) { "String equals is a 'load' that does not conflict with any stores"); assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrIndexOf), "String indexOf is a 'load' that does not conflict with any stores"); + assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrIndexOfChar), + "String indexOfChar is a 'load' that does not conflict with any stores"); assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_AryEq), - "Arrays equals is a 'load' that do not conflict with any stores"); + "Arrays equals is a 'load' that does not conflict with any stores"); + assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_HasNegatives), + "HasNegatives is a 'load' that does not conflict with any stores"); if (!C->alias_type(load_alias_idx)->is_rewritable()) { // It is impossible to spoil this load by putting stores before it, diff --git a/hotspot/src/share/vm/opto/generateOptoStub.cpp b/hotspot/src/share/vm/opto/generateOptoStub.cpp index 5603ffbbd27..b3bc8999daa 100644 --- a/hotspot/src/share/vm/opto/generateOptoStub.cpp +++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp @@ -261,7 +261,7 @@ void GraphKit::gen_stub(address C_function, //----------------------------- // If this is a normal subroutine return, issue the return and be done. - Node *ret; + Node *ret = NULL; switch( is_fancy_jump ) { case 0: // Make a return instruction // Return to caller, free any space for return address diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 3ccdcf6dbe3..397e6cb1c81 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -4266,35 +4266,11 @@ void GraphKit::g1_write_barrier_post(Node* oop_store, #undef __ - -Node* GraphKit::load_String_offset(Node* ctrl, Node* str) { - if (java_lang_String::has_offset_field()) { - int offset_offset = java_lang_String::offset_offset_in_bytes(); - const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), - false, NULL, 0); - const TypePtr* offset_field_type = string_type->add_offset(offset_offset); - int offset_field_idx = C->get_alias_index(offset_field_type); - return make_load(ctrl, - basic_plus_adr(str, str, offset_offset), - TypeInt::INT, T_INT, offset_field_idx, MemNode::unordered); - } else { - return intcon(0); - } -} - Node* GraphKit::load_String_length(Node* ctrl, Node* str) { - if (java_lang_String::has_count_field()) { - int count_offset = java_lang_String::count_offset_in_bytes(); - const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), - false, NULL, 0); - const TypePtr* count_field_type = string_type->add_offset(count_offset); - int count_field_idx = C->get_alias_index(count_field_type); - return make_load(ctrl, - basic_plus_adr(str, str, count_offset), - TypeInt::INT, T_INT, count_field_idx, MemNode::unordered); - } else { - return load_array_length(load_String_value(ctrl, str)); - } + Node* len = load_array_length(load_String_value(ctrl, str)); + Node* coder = load_String_coder(ctrl, str); + // Divide length by 2 if coder is UTF16 + return _gvn.transform(new RShiftINode(len, coder)); } Node* GraphKit::load_String_value(Node* ctrl, Node* str) { @@ -4302,9 +4278,9 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) { const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* value_field_type = string_type->add_offset(value_offset); - const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull, - TypeAry::make(TypeInt::CHAR,TypeInt::POS), - ciTypeArrayKlass::make(T_CHAR), true, 0); + const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull, + TypeAry::make(TypeInt::BYTE, TypeInt::POS), + ciTypeArrayKlass::make(T_BYTE), true, 0); int value_field_idx = C->get_alias_index(value_field_type); Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset), value_type, T_OBJECT, value_field_idx, MemNode::unordered); @@ -4315,14 +4291,21 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) { return load; } -void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) { - int offset_offset = java_lang_String::offset_offset_in_bytes(); - const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), - false, NULL, 0); - const TypePtr* offset_field_type = string_type->add_offset(offset_offset); - int offset_field_idx = C->get_alias_index(offset_field_type); - store_to_memory(ctrl, basic_plus_adr(str, offset_offset), - value, T_INT, offset_field_idx, MemNode::unordered); +Node* GraphKit::load_String_coder(Node* ctrl, Node* str) { + if (java_lang_String::has_coder_field()) { + if (!CompactStrings) { + return intcon(java_lang_String::CODER_UTF16); + } + int coder_offset = java_lang_String::coder_offset_in_bytes(); + const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), + false, NULL, 0); + const TypePtr* coder_field_type = string_type->add_offset(coder_offset); + int coder_field_idx = C->get_alias_index(coder_field_type); + return make_load(ctrl, basic_plus_adr(str, str, coder_offset), + TypeInt::BYTE, T_BYTE, coder_field_idx, MemNode::unordered); + } else { + return intcon(0); // false + } } void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) { @@ -4330,19 +4313,76 @@ void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) { const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* value_field_type = string_type->add_offset(value_offset); - store_oop_to_object(ctrl, str, basic_plus_adr(str, value_offset), value_field_type, - value, TypeAryPtr::CHARS, T_OBJECT, MemNode::unordered); + value, TypeAryPtr::BYTES, T_OBJECT, MemNode::unordered); } -void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) { - int count_offset = java_lang_String::count_offset_in_bytes(); +void GraphKit::store_String_coder(Node* ctrl, Node* str, Node* value) { + int coder_offset = java_lang_String::coder_offset_in_bytes(); const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); - const TypePtr* count_field_type = string_type->add_offset(count_offset); - int count_field_idx = C->get_alias_index(count_field_type); - store_to_memory(ctrl, basic_plus_adr(str, count_offset), - value, T_INT, count_field_idx, MemNode::unordered); + const TypePtr* coder_field_type = string_type->add_offset(coder_offset); + int coder_field_idx = C->get_alias_index(coder_field_type); + store_to_memory(ctrl, basic_plus_adr(str, coder_offset), + value, T_BYTE, coder_field_idx, MemNode::unordered); +} + +Node* GraphKit::compress_string(Node* src, Node* dst, Node* count) { + assert(Matcher::match_rule_supported(Op_StrCompressedCopy), "Intrinsic not supported"); + uint idx = C->get_alias_index(TypeAryPtr::BYTES); + StrCompressedCopyNode* str = new StrCompressedCopyNode(control(), memory(idx), src, dst, count); + Node* res_mem = _gvn.transform(new SCMemProjNode(str)); + set_memory(res_mem, idx); + return str; +} + +void GraphKit::inflate_string(Node* src, Node* dst, Node* count) { + assert(Matcher::match_rule_supported(Op_StrInflatedCopy), "Intrinsic not supported"); + uint idx = C->get_alias_index(TypeAryPtr::BYTES); + StrInflatedCopyNode* str = new StrInflatedCopyNode(control(), memory(idx), src, dst, count); + set_memory(_gvn.transform(str), idx); +} + +void GraphKit::inflate_string_slow(Node* src, Node* dst, Node* start, Node* count) { + /** + * int i_char = start; + * for (int i_byte = 0; i_byte < count; i_byte++) { + * dst[i_char++] = (char)(src[i_byte] & 0xff); + * } + */ + add_predicate(); + RegionNode* head = new RegionNode(3); + head->init_req(1, control()); + gvn().set_type(head, Type::CONTROL); + record_for_igvn(head); + + Node* i_byte = new PhiNode(head, TypeInt::INT); + i_byte->init_req(1, intcon(0)); + gvn().set_type(i_byte, TypeInt::INT); + record_for_igvn(i_byte); + + Node* i_char = new PhiNode(head, TypeInt::INT); + i_char->init_req(1, start); + gvn().set_type(i_char, TypeInt::INT); + record_for_igvn(i_char); + + Node* mem = PhiNode::make(head, memory(TypeAryPtr::BYTES), Type::MEMORY, TypeAryPtr::BYTES); + gvn().set_type(mem, Type::MEMORY); + record_for_igvn(mem); + set_control(head); + set_memory(mem, TypeAryPtr::BYTES); + Node* ch = load_array_element(control(), src, i_byte, TypeAryPtr::BYTES); + Node* st = store_to_memory(control(), array_element_address(dst, i_char, T_BYTE), + AndI(ch, intcon(0xff)), T_CHAR, TypeAryPtr::BYTES, MemNode::unordered); + + IfNode* iff = create_and_map_if(head, Bool(CmpI(i_byte, count), BoolTest::lt), PROB_FAIR, COUNT_UNKNOWN); + head->init_req(2, IfTrue(iff)); + mem->init_req(2, st); + i_byte->init_req(2, AddI(i_byte, intcon(1))); + i_char->init_req(2, AddI(i_char, intcon(2))); + + set_control(IfFalse(iff)); + set_memory(st, TypeAryPtr::BYTES); } Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) { diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index 24dbba08a11..a47047d64ae 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -864,12 +864,14 @@ class GraphKit : public Phase { bool deoptimize_on_exception = false); // java.lang.String helpers - Node* load_String_offset(Node* ctrl, Node* str); Node* load_String_length(Node* ctrl, Node* str); Node* load_String_value(Node* ctrl, Node* str); - void store_String_offset(Node* ctrl, Node* str, Node* value); - void store_String_length(Node* ctrl, Node* str, Node* value); + Node* load_String_coder(Node* ctrl, Node* str); void store_String_value(Node* ctrl, Node* str, Node* value); + void store_String_coder(Node* ctrl, Node* str, Node* value); + Node* compress_string(Node* src, Node* dst, Node* count); + void inflate_string(Node* src, Node* dst, Node* count); + void inflate_string_slow(Node* src, Node* dst, Node* start, Node* count); // Handy for making control flow IfNode* create_and_map_if(Node* ctrl, Node* tst, float prob, float cnt) { diff --git a/hotspot/src/share/vm/opto/idealKit.cpp b/hotspot/src/share/vm/opto/idealKit.cpp index 3038982e648..cbba57eba95 100644 --- a/hotspot/src/share/vm/opto/idealKit.cpp +++ b/hotspot/src/share/vm/opto/idealKit.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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 @@ -530,7 +530,6 @@ void IdealKit::make_leaf_call(const TypeFunc *slow_call_type, "call node must be constructed correctly"); } - void IdealKit::make_leaf_call_no_fp(const TypeFunc *slow_call_type, address slow_call, const char *leaf_name, diff --git a/hotspot/src/share/vm/opto/idealKit.hpp b/hotspot/src/share/vm/opto/idealKit.hpp index 3828d30cc0b..73db4771509 100644 --- a/hotspot/src/share/vm/opto/idealKit.hpp +++ b/hotspot/src/share/vm/opto/idealKit.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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 @@ -183,6 +183,7 @@ class IdealKit: public StackObj { Node* AddI(Node* l, Node* r) { return transform(new AddINode(l, r)); } Node* SubI(Node* l, Node* r) { return transform(new SubINode(l, r)); } Node* AndI(Node* l, Node* r) { return transform(new AndINode(l, r)); } + Node* OrI(Node* l, Node* r) { return transform(new OrINode(l, r)); } Node* MaxI(Node* l, Node* r) { return transform(new MaxINode(l, r)); } Node* LShiftI(Node* l, Node* r) { return transform(new LShiftINode(l, r)); } Node* CmpI(Node* l, Node* r) { return transform(new CmpINode(l, r)); } @@ -256,7 +257,6 @@ class IdealKit: public StackObj { Node* parm1, Node* parm2, Node* parm3); - }; #endif // SHARE_VM_OPTO_IDEALKIT_HPP diff --git a/hotspot/src/share/vm/opto/intrinsicnode.cpp b/hotspot/src/share/vm/opto/intrinsicnode.cpp index 683cad55fed..e72c3e221e1 100644 --- a/hotspot/src/share/vm/opto/intrinsicnode.cpp +++ b/hotspot/src/share/vm/opto/intrinsicnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ uint StrIntrinsicNode::match_edge(uint idx) const { //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. Strip out // control copies -Node *StrIntrinsicNode::Ideal(PhaseGVN *phase, bool can_reshape) { +Node* StrIntrinsicNode::Ideal(PhaseGVN* phase, bool can_reshape) { if (remove_dead_region(phase, can_reshape)) return this; // Don't bother trying to transform a dead node if (in(0) && in(0)->is_top()) return NULL; @@ -55,11 +55,29 @@ Node *StrIntrinsicNode::Ideal(PhaseGVN *phase, bool can_reshape) { } //------------------------------Value------------------------------------------ -const Type *StrIntrinsicNode::Value( PhaseTransform *phase ) const { +const Type* StrIntrinsicNode::Value(PhaseTransform* phase) const { if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP; return bottom_type(); } +uint StrIntrinsicNode::size_of() const { return sizeof(*this); } + +//============================================================================= +//------------------------------Ideal------------------------------------------ +// Return a node which is more "ideal" than the current node. Strip out +// control copies +Node* StrCompressedCopyNode::Ideal(PhaseGVN* phase, bool can_reshape) { + return remove_dead_region(phase, can_reshape) ? this : NULL; +} + +//============================================================================= +//------------------------------Ideal------------------------------------------ +// Return a node which is more "ideal" than the current node. Strip out +// control copies +Node* StrInflatedCopyNode::Ideal(PhaseGVN* phase, bool can_reshape) { + return remove_dead_region(phase, can_reshape) ? this : NULL; +} + //============================================================================= //------------------------------match_edge------------------------------------- // Do not match memory edge @@ -70,12 +88,12 @@ uint EncodeISOArrayNode::match_edge(uint idx) const { //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. Strip out // control copies -Node *EncodeISOArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { +Node* EncodeISOArrayNode::Ideal(PhaseGVN* phase, bool can_reshape) { return remove_dead_region(phase, can_reshape) ? this : NULL; } //------------------------------Value------------------------------------------ -const Type *EncodeISOArrayNode::Value(PhaseTransform *phase) const { +const Type* EncodeISOArrayNode::Value(PhaseTransform* phase) const { if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP; return bottom_type(); } diff --git a/hotspot/src/share/vm/opto/intrinsicnode.hpp b/hotspot/src/share/vm/opto/intrinsicnode.hpp index 2f19db6474b..d5bc0c70742 100644 --- a/hotspot/src/share/vm/opto/intrinsicnode.hpp +++ b/hotspot/src/share/vm/opto/intrinsicnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -35,75 +35,131 @@ // hit (cache is checked with exposed code in gen_subtype_check()). Return // not zero for a miss or zero for a hit. class PartialSubtypeCheckNode : public Node { - public: + public: PartialSubtypeCheckNode(Node* c, Node* sub, Node* super) : Node(c,sub,super) {} virtual int Opcode() const; - virtual const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } + virtual const Type* bottom_type() const { return TypeRawPtr::BOTTOM; } virtual uint ideal_reg() const { return Op_RegP; } }; //------------------------------StrIntrinsic------------------------------- -// Base class for Ideal nodes used in String instrinsic code. +// Base class for Ideal nodes used in String intrinsic code. class StrIntrinsicNode: public Node { - public: + public: + // Possible encodings of the two parameters passed to the string intrinsic. + // 'L' stands for Latin1 and 'U' stands for UTF16. For example, 'LU' means that + // the first string is Latin1 encoded and the second string is UTF16 encoded. + typedef enum ArgEncoding { LL, LU, UL, UU, none } ArgEnc; + + protected: + // Encoding of strings. Used to select the right version of the intrinsic. + const ArgEncoding _encoding; + virtual uint size_of() const; + + public: StrIntrinsicNode(Node* control, Node* char_array_mem, - Node* s1, Node* c1, Node* s2, Node* c2): - Node(control, char_array_mem, s1, c1, s2, c2) { + Node* s1, Node* c1, Node* s2, Node* c2, ArgEncoding encoding): + Node(control, char_array_mem, s1, c1, s2, c2), _encoding(encoding) { } StrIntrinsicNode(Node* control, Node* char_array_mem, - Node* s1, Node* s2, Node* c): - Node(control, char_array_mem, s1, s2, c) { + Node* s1, Node* s2, Node* c, ArgEncoding encoding): + Node(control, char_array_mem, s1, s2, c), _encoding(encoding) { } StrIntrinsicNode(Node* control, Node* char_array_mem, - Node* s1, Node* s2): - Node(control, char_array_mem, s1, s2) { + Node* s1, Node* s2, ArgEncoding encoding): + Node(control, char_array_mem, s1, s2), _encoding(encoding) { } virtual bool depends_only_on_test() const { return false; } - virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; } + virtual const TypePtr* adr_type() const { return TypeAryPtr::BYTES; } virtual uint match_edge(uint idx) const; virtual uint ideal_reg() const { return Op_RegI; } - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); - virtual const Type *Value(PhaseTransform *phase) const; + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + virtual const Type* Value(PhaseTransform* phase) const; + ArgEncoding encoding() const { return _encoding; } }; //------------------------------StrComp------------------------------------- class StrCompNode: public StrIntrinsicNode { - public: + public: StrCompNode(Node* control, Node* char_array_mem, - Node* s1, Node* c1, Node* s2, Node* c2): - StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2) {}; + Node* s1, Node* c1, Node* s2, Node* c2, ArgEncoding encoding): + StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2, encoding) {}; virtual int Opcode() const; virtual const Type* bottom_type() const { return TypeInt::INT; } }; //------------------------------StrEquals------------------------------------- class StrEqualsNode: public StrIntrinsicNode { - public: + public: StrEqualsNode(Node* control, Node* char_array_mem, - Node* s1, Node* s2, Node* c): - StrIntrinsicNode(control, char_array_mem, s1, s2, c) {}; + Node* s1, Node* s2, Node* c, ArgEncoding encoding): + StrIntrinsicNode(control, char_array_mem, s1, s2, c, encoding) {}; virtual int Opcode() const; virtual const Type* bottom_type() const { return TypeInt::BOOL; } }; //------------------------------StrIndexOf------------------------------------- class StrIndexOfNode: public StrIntrinsicNode { - public: + public: StrIndexOfNode(Node* control, Node* char_array_mem, - Node* s1, Node* c1, Node* s2, Node* c2): - StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2) {}; + Node* s1, Node* c1, Node* s2, Node* c2, ArgEncoding encoding): + StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2, encoding) {}; virtual int Opcode() const; virtual const Type* bottom_type() const { return TypeInt::INT; } }; +//------------------------------StrIndexOfChar------------------------------------- +class StrIndexOfCharNode: public StrIntrinsicNode { + public: + StrIndexOfCharNode(Node* control, Node* char_array_mem, + Node* s1, Node* c1, Node* c, ArgEncoding encoding): + StrIntrinsicNode(control, char_array_mem, s1, c1, c, encoding) {}; + virtual int Opcode() const; + virtual const Type* bottom_type() const { return TypeInt::INT; } +}; + +//--------------------------StrCompressedCopy------------------------------- +class StrCompressedCopyNode: public StrIntrinsicNode { + public: + StrCompressedCopyNode(Node* control, Node* arymem, + Node* s1, Node* s2, Node* c): + StrIntrinsicNode(control, arymem, s1, s2, c, none) {}; + virtual int Opcode() const; + virtual const Type* bottom_type() const { return TypeInt::INT; } + virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); +}; + +//--------------------------StrInflatedCopy--------------------------------- +class StrInflatedCopyNode: public StrIntrinsicNode { + public: + StrInflatedCopyNode(Node* control, Node* arymem, + Node* s1, Node* s2, Node* c): + StrIntrinsicNode(control, arymem, s1, s2, c, none) {}; + virtual int Opcode() const; + virtual const Type* bottom_type() const { return Type::MEMORY; } + virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); +}; + //------------------------------AryEq--------------------------------------- class AryEqNode: public StrIntrinsicNode { - public: - AryEqNode(Node* control, Node* char_array_mem, Node* s1, Node* s2): - StrIntrinsicNode(control, char_array_mem, s1, s2) {}; + public: + AryEqNode(Node* control, Node* char_array_mem, + Node* s1, Node* s2, ArgEncoding encoding): + StrIntrinsicNode(control, char_array_mem, s1, s2, encoding) {}; + virtual int Opcode() const; + virtual const Type* bottom_type() const { return TypeInt::BOOL; } +}; + +//------------------------------HasNegatives--------------------------------- +class HasNegativesNode: public StrIntrinsicNode { + public: + HasNegativesNode(Node* control, Node* char_array_mem, Node* s1, Node* c1): + StrIntrinsicNode(control, char_array_mem, s1, c1, none) {}; virtual int Opcode() const; virtual const Type* bottom_type() const { return TypeInt::BOOL; } }; @@ -112,16 +168,16 @@ class AryEqNode: public StrIntrinsicNode { //------------------------------EncodeISOArray-------------------------------- // encode char[] to byte[] in ISO_8859_1 class EncodeISOArrayNode: public Node { - public: - EncodeISOArrayNode(Node *control, Node* arymem, Node* s1, Node* s2, Node* c): Node(control, arymem, s1, s2, c) {}; + public: + EncodeISOArrayNode(Node* control, Node* arymem, Node* s1, Node* s2, Node* c): Node(control, arymem, s1, s2, c) {}; virtual int Opcode() const; virtual bool depends_only_on_test() const { return false; } virtual const Type* bottom_type() const { return TypeInt::INT; } virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } virtual uint match_edge(uint idx) const; virtual uint ideal_reg() const { return Op_RegI; } - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); - virtual const Type *Value(PhaseTransform *phase) const; + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + virtual const Type* Value(PhaseTransform* phase) const; }; #endif // SHARE_VM_OPTO_INTRINSICNODE_HPP diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 01a21cd48e9..1dd92fa610f 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -196,8 +196,12 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_StrIndexOfChar: case Op_AryEq: + case Op_StrInflatedCopy: + case Op_StrCompressedCopy: case Op_EncodeISOArray: + case Op_HasNegatives: // Not a legit memory op for implicit null check regardless of // embedded loads continue; @@ -806,7 +810,7 @@ uint PhaseCFG::sched_call(Block* block, uint node_cnt, Node_List& worklist, Grow block->insert_node(proj, node_cnt++); // Select the right register save policy. - const char * save_policy; + const char *save_policy = NULL; switch (op) { case Op_CallRuntime: case Op_CallLeaf: diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 4c27dab9b03..c1f744c5be0 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -200,12 +200,16 @@ class LibraryCallKit : public GraphKit { } Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls); - Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2); - Node* make_string_method_node(int opcode, Node* str1, Node* str2); - bool inline_string_compareTo(); - bool inline_string_indexOf(); - Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); - bool inline_string_equals(); + Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae); + bool inline_string_compareTo(StrIntrinsicNode::ArgEnc ae); + bool inline_string_indexOf(StrIntrinsicNode::ArgEnc ae); + bool inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae); + bool inline_string_indexOfChar(); + bool inline_string_equals(StrIntrinsicNode::ArgEnc ae); + bool inline_string_toBytesU(); + bool inline_string_getCharsU(); + bool inline_string_copy(bool compress); + bool inline_string_char_access(bool is_store); Node* round_double_node(Node* n); bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); bool inline_math_native(vmIntrinsics::ID id); @@ -251,7 +255,7 @@ class LibraryCallKit : public GraphKit { bool inline_native_newArray(); bool inline_native_getLength(); bool inline_array_copyOf(bool is_copyOfRange); - bool inline_array_equals(); + bool inline_array_equals(StrIntrinsicNode::ArgEnc ae); void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark); bool inline_native_clone(bool is_virtual); bool inline_native_Reflection_getCallerClass(); @@ -298,6 +302,7 @@ class LibraryCallKit : public GraphKit { bool inline_updateBytesAdler32(); bool inline_updateByteBufferAdler32(); bool inline_multiplyToLen(); + bool inline_hasNegatives(); bool inline_squareToLen(); bool inline_mulAdd(); bool inline_montgomeryMultiply(); @@ -458,6 +463,7 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms, int predicate) { bool LibraryCallKit::try_to_inline(int predicate) { // Handle symbolic names for otherwise undistinguished boolean switches: const bool is_store = true; + const bool is_compress = true; const bool is_native_ptr = true; const bool is_static = true; const bool is_volatile = true; @@ -512,9 +518,31 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_arraycopy: return inline_arraycopy(); - case vmIntrinsics::_compareTo: return inline_string_compareTo(); - case vmIntrinsics::_indexOf: return inline_string_indexOf(); - case vmIntrinsics::_equals: return inline_string_equals(); + case vmIntrinsics::_compareToL: return inline_string_compareTo(StrIntrinsicNode::LL); + case vmIntrinsics::_compareToU: return inline_string_compareTo(StrIntrinsicNode::UU); + case vmIntrinsics::_compareToLU: return inline_string_compareTo(StrIntrinsicNode::LU); + case vmIntrinsics::_compareToUL: return inline_string_compareTo(StrIntrinsicNode::UL); + + case vmIntrinsics::_indexOfL: return inline_string_indexOf(StrIntrinsicNode::LL); + case vmIntrinsics::_indexOfU: return inline_string_indexOf(StrIntrinsicNode::UU); + case vmIntrinsics::_indexOfUL: return inline_string_indexOf(StrIntrinsicNode::UL); + case vmIntrinsics::_indexOfIL: return inline_string_indexOfI(StrIntrinsicNode::LL); + case vmIntrinsics::_indexOfIU: return inline_string_indexOfI(StrIntrinsicNode::UU); + case vmIntrinsics::_indexOfIUL: return inline_string_indexOfI(StrIntrinsicNode::UL); + case vmIntrinsics::_indexOfU_char: return inline_string_indexOfChar(); + + case vmIntrinsics::_equalsL: return inline_string_equals(StrIntrinsicNode::LL); + case vmIntrinsics::_equalsU: return inline_string_equals(StrIntrinsicNode::UU); + + case vmIntrinsics::_toBytesStringU: return inline_string_toBytesU(); + case vmIntrinsics::_getCharsStringU: return inline_string_getCharsU(); + case vmIntrinsics::_getCharStringU: return inline_string_char_access(!is_store); + case vmIntrinsics::_putCharStringU: return inline_string_char_access( is_store); + + case vmIntrinsics::_compressStringC: + case vmIntrinsics::_compressStringB: return inline_string_copy( is_compress); + case vmIntrinsics::_inflateStringC: + case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress); case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, !is_volatile); case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, !is_volatile); @@ -617,7 +645,8 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_getLength: return inline_native_getLength(); case vmIntrinsics::_copyOf: return inline_array_copyOf(false); case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true); - case vmIntrinsics::_equalsC: return inline_array_equals(); + case vmIntrinsics::_equalsB: return inline_array_equals(StrIntrinsicNode::LL); + case vmIntrinsics::_equalsC: return inline_array_equals(StrIntrinsicNode::UU); case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual()); case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check(); @@ -687,6 +716,7 @@ bool LibraryCallKit::try_to_inline(int predicate) { return inline_ghash_processBlocks(); case vmIntrinsics::_encodeISOArray: + case vmIntrinsics::_encodeByteISOArray: return inline_encodeISOArray(); case vmIntrinsics::_updateCRC32: @@ -711,6 +741,9 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_isCompileConstant: return inline_isCompileConstant(); + case vmIntrinsics::_hasNegatives: + return inline_hasNegatives(); + default: // If you get here, it may be that someone has added a new intrinsic // to the list in vmSymbols.hpp without implementing it here. @@ -876,75 +909,24 @@ Node* LibraryCallKit::generate_current_thread(Node* &tls_output) { //------------------------------make_string_method_node------------------------ -// Helper method for String intrinsic functions. This version is called -// with str1 and str2 pointing to String object nodes. -// -Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2) { - Node* no_ctrl = NULL; - - // Get start addr of string - Node* str1_value = load_String_value(no_ctrl, str1); - Node* str1_offset = load_String_offset(no_ctrl, str1); - Node* str1_start = array_element_address(str1_value, str1_offset, T_CHAR); - - // Get length of string 1 - Node* str1_len = load_String_length(no_ctrl, str1); - - Node* str2_value = load_String_value(no_ctrl, str2); - Node* str2_offset = load_String_offset(no_ctrl, str2); - Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR); - - Node* str2_len = NULL; - Node* result = NULL; - - switch (opcode) { - case Op_StrIndexOf: - // Get length of string 2 - str2_len = load_String_length(no_ctrl, str2); - - result = new StrIndexOfNode(control(), memory(TypeAryPtr::CHARS), - str1_start, str1_len, str2_start, str2_len); - break; - case Op_StrComp: - // Get length of string 2 - str2_len = load_String_length(no_ctrl, str2); - - result = new StrCompNode(control(), memory(TypeAryPtr::CHARS), - str1_start, str1_len, str2_start, str2_len); - break; - case Op_StrEquals: - result = new StrEqualsNode(control(), memory(TypeAryPtr::CHARS), - str1_start, str2_start, str1_len); - break; - default: - ShouldNotReachHere(); - return NULL; - } - - // All these intrinsics have checks. - C->set_has_split_ifs(true); // Has chance for split-if optimization - - return _gvn.transform(result); -} - -// Helper method for String intrinsic functions. This version is called -// with str1 and str2 pointing to char[] nodes, with cnt1 and cnt2 pointing -// to Int nodes containing the lenghts of str1 and str2. -// -Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2) { +// Helper method for String intrinsic functions. This version is called with +// str1 and str2 pointing to byte[] nodes containing Latin1 or UTF16 encoded +// characters (depending on 'is_byte'). cnt1 and cnt2 are pointing to Int nodes +// containing the lengths of str1 and str2. +Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae) { Node* result = NULL; switch (opcode) { case Op_StrIndexOf: - result = new StrIndexOfNode(control(), memory(TypeAryPtr::CHARS), - str1_start, cnt1, str2_start, cnt2); + result = new StrIndexOfNode(control(), memory(TypeAryPtr::BYTES), + str1_start, cnt1, str2_start, cnt2, ae); break; case Op_StrComp: - result = new StrCompNode(control(), memory(TypeAryPtr::CHARS), - str1_start, cnt1, str2_start, cnt2); + result = new StrCompNode(control(), memory(TypeAryPtr::BYTES), + str1_start, cnt1, str2_start, cnt2, ae); break; case Op_StrEquals: - result = new StrEqualsNode(control(), memory(TypeAryPtr::CHARS), - str1_start, str2_start, cnt1); + result = new StrEqualsNode(control(), memory(TypeAryPtr::BYTES), + str1_start, str2_start, cnt1, ae); break; default: ShouldNotReachHere(); @@ -958,98 +940,54 @@ Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node } //------------------------------inline_string_compareTo------------------------ -// public int java.lang.String.compareTo(String anotherString); -bool LibraryCallKit::inline_string_compareTo() { - Node* receiver = null_check(argument(0)); - Node* arg = null_check(argument(1)); - if (stopped()) { - return true; - } - set_result(make_string_method_node(Op_StrComp, receiver, arg)); +bool LibraryCallKit::inline_string_compareTo(StrIntrinsicNode::ArgEnc ae) { + Node* arg1 = argument(0); + Node* arg2 = argument(1); + + // Get start addr and length of first argument + Node* arg1_start = array_element_address(arg1, intcon(0), T_BYTE); + Node* arg1_cnt = load_array_length(arg1); + + // Get start addr and length of second argument + Node* arg2_start = array_element_address(arg2, intcon(0), T_BYTE); + Node* arg2_cnt = load_array_length(arg2); + + Node* result = make_string_method_node(Op_StrComp, arg1_start, arg1_cnt, arg2_start, arg2_cnt, ae); + set_result(result); return true; } //------------------------------inline_string_equals------------------------ -bool LibraryCallKit::inline_string_equals() { - Node* receiver = null_check_receiver(); - // NOTE: Do not null check argument for String.equals() because spec - // allows to specify NULL as argument. - Node* argument = this->argument(1); - if (stopped()) { - return true; - } +bool LibraryCallKit::inline_string_equals(StrIntrinsicNode::ArgEnc ae) { + Node* arg1 = argument(0); + Node* arg2 = argument(1); // paths (plus control) merge - RegionNode* region = new RegionNode(5); + RegionNode* region = new RegionNode(3); Node* phi = new PhiNode(region, TypeInt::BOOL); - // does source == target string? - Node* cmp = _gvn.transform(new CmpPNode(receiver, argument)); - Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq)); - - Node* if_eq = generate_slow_guard(bol, NULL); - if (if_eq != NULL) { - // receiver == argument - phi->init_req(2, intcon(1)); - region->init_req(2, if_eq); - } - - // get String klass for instanceOf - ciInstanceKlass* klass = env()->String_klass(); - if (!stopped()) { - Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); - Node* cmp = _gvn.transform(new CmpINode(inst, intcon(1))); - Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne)); + // Get start addr and length of first argument + Node* arg1_start = array_element_address(arg1, intcon(0), T_BYTE); + Node* arg1_cnt = load_array_length(arg1); - Node* inst_false = generate_guard(bol, NULL, PROB_MIN); - //instanceOf == true, fallthrough + // Get start addr and length of second argument + Node* arg2_start = array_element_address(arg2, intcon(0), T_BYTE); + Node* arg2_cnt = load_array_length(arg2); - if (inst_false != NULL) { - phi->init_req(3, intcon(0)); - region->init_req(3, inst_false); - } - } - - if (!stopped()) { - const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass); - - // Properly cast the argument to String - argument = _gvn.transform(new CheckCastPPNode(control(), argument, string_type)); - // This path is taken only when argument's type is String:NotNull. - argument = cast_not_null(argument, false); - - Node* no_ctrl = NULL; - - // Get start addr of receiver - Node* receiver_val = load_String_value(no_ctrl, receiver); - Node* receiver_offset = load_String_offset(no_ctrl, receiver); - Node* receiver_start = array_element_address(receiver_val, receiver_offset, T_CHAR); - - // Get length of receiver - Node* receiver_cnt = load_String_length(no_ctrl, receiver); - - // Get start addr of argument - Node* argument_val = load_String_value(no_ctrl, argument); - Node* argument_offset = load_String_offset(no_ctrl, argument); - Node* argument_start = array_element_address(argument_val, argument_offset, T_CHAR); - - // Get length of argument - Node* argument_cnt = load_String_length(no_ctrl, argument); - - // Check for receiver count != argument count - Node* cmp = _gvn.transform(new CmpINode(receiver_cnt, argument_cnt)); + // Check for arg1_cnt != arg2_cnt + Node* cmp = _gvn.transform(new CmpINode(arg1_cnt, arg2_cnt)); Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne)); Node* if_ne = generate_slow_guard(bol, NULL); if (if_ne != NULL) { - phi->init_req(4, intcon(0)); - region->init_req(4, if_ne); + phi->init_req(2, intcon(0)); + region->init_req(2, if_ne); } // Check for count == 0 is done by assembler code for StrEquals. if (!stopped()) { - Node* equals = make_string_method_node(Op_StrEquals, receiver_start, receiver_cnt, argument_start, argument_cnt); + Node* equals = make_string_method_node(Op_StrEquals, arg1_start, arg1_cnt, arg2_start, arg2_cnt, ae); phi->init_req(1, equals); region->init_req(1, control()); } @@ -1064,289 +1002,462 @@ bool LibraryCallKit::inline_string_equals() { } //------------------------------inline_array_equals---------------------------- -bool LibraryCallKit::inline_array_equals() { +bool LibraryCallKit::inline_array_equals(StrIntrinsicNode::ArgEnc ae) { + assert(ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::LL, "unsupported array types"); Node* arg1 = argument(0); Node* arg2 = argument(1); - set_result(_gvn.transform(new AryEqNode(control(), memory(TypeAryPtr::CHARS), arg1, arg2))); + + const TypeAryPtr* mtype = (ae == StrIntrinsicNode::UU) ? TypeAryPtr::CHARS : TypeAryPtr::BYTES; + set_result(_gvn.transform(new AryEqNode(control(), memory(mtype), arg1, arg2, ae))); return true; } -// Java version of String.indexOf(constant string) -// class StringDecl { -// StringDecl(char[] ca) { -// offset = 0; -// count = ca.length; -// value = ca; -// } -// int offset; -// int count; -// char[] value; -// } -// -// static int string_indexOf_J(StringDecl string_object, char[] target_object, -// int targetOffset, int cache_i, int md2) { -// int cache = cache_i; -// int sourceOffset = string_object.offset; -// int sourceCount = string_object.count; -// int targetCount = target_object.length; -// -// int targetCountLess1 = targetCount - 1; -// int sourceEnd = sourceOffset + sourceCount - targetCountLess1; -// -// char[] source = string_object.value; -// char[] target = target_object; -// int lastChar = target[targetCountLess1]; -// -// outer_loop: -// for (int i = sourceOffset; i < sourceEnd; ) { -// int src = source[i + targetCountLess1]; -// if (src == lastChar) { -// // With random strings and a 4-character alphabet, -// // reverse matching at this point sets up 0.8% fewer -// // frames, but (paradoxically) makes 0.3% more probes. -// // Since those probes are nearer the lastChar probe, -// // there is may be a net D$ win with reverse matching. -// // But, reversing loop inhibits unroll of inner loop -// // for unknown reason. So, does running outer loop from -// // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount) -// for (int j = 0; j < targetCountLess1; j++) { -// if (target[targetOffset + j] != source[i+j]) { -// if ((cache & (1 << source[i+j])) == 0) { -// if (md2 < j+1) { -// i += j+1; -// continue outer_loop; -// } -// } -// i += md2; -// continue outer_loop; -// } -// } -// return i - sourceOffset; -// } -// if ((cache & (1 << src)) == 0) { -// i += targetCountLess1; -// } // using "i += targetCount;" and an "else i++;" causes a jump to jump. -// i++; -// } -// return -1; -// } +//------------------------------inline_hasNegatives------------------------------ +bool LibraryCallKit::inline_hasNegatives() { + if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; -//------------------------------string_indexOf------------------------ -Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_array, jint targetOffset_i, - jint cache_i, jint md2_i) { + assert(callee()->signature()->size() == 3, "hasNegatives has 3 parameters"); + // no receiver since it is static method + Node* ba = argument(0); + Node* offset = argument(1); + Node* len = argument(2); - Node* no_ctrl = NULL; - float likely = PROB_LIKELY(0.9); - float unlikely = PROB_UNLIKELY(0.9); + RegionNode* bailout = new RegionNode(1); + record_for_igvn(bailout); - const int nargs = 0; // no arguments to push back for uncommon trap in predicate + // offset must not be negative. + generate_negative_guard(offset, bailout); - Node* source = load_String_value(no_ctrl, string_object); - Node* sourceOffset = load_String_offset(no_ctrl, string_object); - Node* sourceCount = load_String_length(no_ctrl, string_object); + // offset + length must not exceed length of ba. + generate_limit_guard(offset, len, load_array_length(ba), bailout); - Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true))); - jint target_length = target_array->length(); - const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin)); - const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot); - - // String.value field is known to be @Stable. - if (UseImplicitStableValues) { - target = cast_array_to_stable(target, target_type); + if (bailout->req() > 1) { + PreserveJVMState pjvms(this); + set_control(_gvn.transform(bailout)); + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_maybe_recompile); } - - IdealKit kit(this, false, true); -#define __ kit. - Node* zero = __ ConI(0); - Node* one = __ ConI(1); - Node* cache = __ ConI(cache_i); - Node* md2 = __ ConI(md2_i); - Node* lastChar = __ ConI(target_array->char_at(target_length - 1)); - Node* targetCountLess1 = __ ConI(target_length - 1); - Node* targetOffset = __ ConI(targetOffset_i); - Node* sourceEnd = __ SubI(__ AddI(sourceOffset, sourceCount), targetCountLess1); - - IdealVariable rtn(kit), i(kit), j(kit); __ declarations_done(); - Node* outer_loop = __ make_label(2 /* goto */); - Node* return_ = __ make_label(1); - - __ set(rtn,__ ConI(-1)); - __ loop(this, nargs, i, sourceOffset, BoolTest::lt, sourceEnd); { - Node* i2 = __ AddI(__ value(i), targetCountLess1); - // pin to prohibit loading of "next iteration" value which may SEGV (rare) - Node* src = load_array_element(__ ctrl(), source, i2, TypeAryPtr::CHARS); - __ if_then(src, BoolTest::eq, lastChar, unlikely); { - __ loop(this, nargs, j, zero, BoolTest::lt, targetCountLess1); { - Node* tpj = __ AddI(targetOffset, __ value(j)); - Node* targ = load_array_element(no_ctrl, target, tpj, target_type); - Node* ipj = __ AddI(__ value(i), __ value(j)); - Node* src2 = load_array_element(no_ctrl, source, ipj, TypeAryPtr::CHARS); - __ if_then(targ, BoolTest::ne, src2); { - __ if_then(__ AndI(cache, __ LShiftI(one, src2)), BoolTest::eq, zero); { - __ if_then(md2, BoolTest::lt, __ AddI(__ value(j), one)); { - __ increment(i, __ AddI(__ value(j), one)); - __ goto_(outer_loop); - } __ end_if(); __ dead(j); - }__ end_if(); __ dead(j); - __ increment(i, md2); - __ goto_(outer_loop); - }__ end_if(); - __ increment(j, one); - }__ end_loop(); __ dead(j); - __ set(rtn, __ SubI(__ value(i), sourceOffset)); __ dead(i); - __ goto_(return_); - }__ end_if(); - __ if_then(__ AndI(cache, __ LShiftI(one, src)), BoolTest::eq, zero, likely); { - __ increment(i, targetCountLess1); - }__ end_if(); - __ increment(i, one); - __ bind(outer_loop); - }__ end_loop(); __ dead(i); - __ bind(return_); - - // Final sync IdealKit and GraphKit. - final_sync(kit); - Node* result = __ value(rtn); -#undef __ - C->set_has_loops(true); - return result; + if (!stopped()) { + Node* ba_start = array_element_address(ba, offset, T_BYTE); + Node* result = new HasNegativesNode(control(), memory(TypeAryPtr::BYTES), ba_start, len); + set_result(_gvn.transform(result)); + } + return true; } //------------------------------inline_string_indexOf------------------------ -bool LibraryCallKit::inline_string_indexOf() { - Node* receiver = argument(0); - Node* arg = argument(1); - - Node* result; - if (Matcher::has_match_rule(Op_StrIndexOf) && - UseSSE42Intrinsics) { - // Generate SSE4.2 version of indexOf - // We currently only have match rules that use SSE4.2 - - receiver = null_check(receiver); - arg = null_check(arg); - if (stopped()) { - return true; - } - - // Make the merge point - RegionNode* result_rgn = new RegionNode(4); - Node* result_phi = new PhiNode(result_rgn, TypeInt::INT); - Node* no_ctrl = NULL; - - // Get start addr of source string - Node* source = load_String_value(no_ctrl, receiver); - Node* source_offset = load_String_offset(no_ctrl, receiver); - Node* source_start = array_element_address(source, source_offset, T_CHAR); - - // Get length of source string - Node* source_cnt = load_String_length(no_ctrl, receiver); - - // Get start addr of substring - Node* substr = load_String_value(no_ctrl, arg); - Node* substr_offset = load_String_offset(no_ctrl, arg); - Node* substr_start = array_element_address(substr, substr_offset, T_CHAR); - - // Get length of source string - Node* substr_cnt = load_String_length(no_ctrl, arg); - - // Check for substr count > string count - Node* cmp = _gvn.transform(new CmpINode(substr_cnt, source_cnt)); - Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::gt)); - Node* if_gt = generate_slow_guard(bol, NULL); - if (if_gt != NULL) { - result_phi->init_req(2, intcon(-1)); - result_rgn->init_req(2, if_gt); - } - - if (!stopped()) { - // Check for substr count == 0 - cmp = _gvn.transform(new CmpINode(substr_cnt, intcon(0))); - bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq)); - Node* if_zero = generate_slow_guard(bol, NULL); - if (if_zero != NULL) { - result_phi->init_req(3, intcon(0)); - result_rgn->init_req(3, if_zero); - } - } - - if (!stopped()) { - result = make_string_method_node(Op_StrIndexOf, source_start, source_cnt, substr_start, substr_cnt); - result_phi->init_req(1, result); - result_rgn->init_req(1, control()); - } - set_control(_gvn.transform(result_rgn)); - record_for_igvn(result_rgn); - result = _gvn.transform(result_phi); - - } else { // Use LibraryCallKit::string_indexOf - // don't intrinsify if argument isn't a constant string. - if (!arg->is_Con()) { - return false; - } - const TypeOopPtr* str_type = _gvn.type(arg)->isa_oopptr(); - if (str_type == NULL) { - return false; - } - ciInstanceKlass* klass = env()->String_klass(); - ciObject* str_const = str_type->const_oop(); - if (str_const == NULL || str_const->klass() != klass) { - return false; - } - ciInstance* str = str_const->as_instance(); - assert(str != NULL, "must be instance"); - - ciObject* v = str->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object(); - ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array - - int o; - int c; - if (java_lang_String::has_offset_field()) { - o = str->field_value_by_offset(java_lang_String::offset_offset_in_bytes()).as_int(); - c = str->field_value_by_offset(java_lang_String::count_offset_in_bytes()).as_int(); - } else { - o = 0; - c = pat->length(); - } - - // constant strings have no offset and count == length which - // simplifies the resulting code somewhat so lets optimize for that. - if (o != 0 || c != pat->length()) { - return false; - } - - receiver = null_check(receiver, T_OBJECT); - // NOTE: No null check on the argument is needed since it's a constant String oop. - if (stopped()) { - return true; - } - - // The null string as a pattern always returns 0 (match at beginning of string) - if (c == 0) { - set_result(intcon(0)); - return true; - } - - // Generate default indexOf - jchar lastChar = pat->char_at(o + (c - 1)); - int cache = 0; - int i; - for (i = 0; i < c - 1; i++) { - assert(i < pat->length(), "out of range"); - cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); - } - - int md2 = c; - for (i = 0; i < c - 1; i++) { - assert(i < pat->length(), "out of range"); - if (pat->char_at(o + i) == lastChar) { - md2 = (c - 1) - i; - } - } - - result = string_indexOf(receiver, pat, o, cache, md2); +bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) { + if (!Matcher::has_match_rule(Op_StrIndexOf) || !UseSSE42Intrinsics) { + return false; + } + Node* src = argument(0); + Node* tgt = argument(1); + + // Make the merge point + RegionNode* result_rgn = new RegionNode(4); + Node* result_phi = new PhiNode(result_rgn, TypeInt::INT); + + // Get start addr and length of source string + Node* src_start = array_element_address(src, intcon(0), T_BYTE); + Node* src_count = load_array_length(src); + + // Get start addr and length of substring + Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE); + Node* tgt_count = load_array_length(tgt); + + if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) { + // Divide src size by 2 if String is UTF16 encoded + src_count = _gvn.transform(new RShiftINode(src_count, intcon(1))); + } + if (ae == StrIntrinsicNode::UU) { + // Divide substring size by 2 if String is UTF16 encoded + tgt_count = _gvn.transform(new RShiftINode(tgt_count, intcon(1))); + } + + // Check for substr count > string count + Node* cmp = _gvn.transform(new CmpINode(tgt_count, src_count)); + Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::gt)); + Node* if_gt = generate_slow_guard(bol, NULL); + if (if_gt != NULL) { + result_phi->init_req(2, intcon(-1)); + result_rgn->init_req(2, if_gt); + } + + if (!stopped()) { + // Check for substr count == 0 + cmp = _gvn.transform(new CmpINode(tgt_count, intcon(0))); + bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq)); + Node* if_zero = generate_slow_guard(bol, NULL); + if (if_zero != NULL) { + result_phi->init_req(3, intcon(0)); + result_rgn->init_req(3, if_zero); + } + } + + if (!stopped()) { + Node* result = make_string_method_node(Op_StrIndexOf, src_start, src_count, tgt_start, tgt_count, ae); + result_phi->init_req(1, result); + result_rgn->init_req(1, control()); + } + set_control(_gvn.transform(result_rgn)); + record_for_igvn(result_rgn); + set_result(_gvn.transform(result_phi)); + + return true; +} + +//-----------------------------inline_string_indexOf----------------------- +bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) { + if (!Matcher::has_match_rule(Op_StrIndexOf) || !UseSSE42Intrinsics) { + return false; + } + assert(callee()->signature()->size() == 5, "String.indexOf() has 5 arguments"); + Node* src = argument(0); // byte[] + Node* src_count = argument(1); + Node* tgt = argument(2); // byte[] + Node* tgt_count = argument(3); + Node* from_index = argument(4); + + // Java code which calls this method has range checks for from_index value. + src_count = _gvn.transform(new SubINode(src_count, from_index)); + + // Multiply byte array index by 2 if String is UTF16 encoded + Node* src_offset = (ae == StrIntrinsicNode::LL) ? from_index : _gvn.transform(new LShiftINode(from_index, intcon(1))); + Node* src_start = array_element_address(src, src_offset, T_BYTE); + Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE); + + Node* result = make_string_method_node(Op_StrIndexOf, src_start, src_count, tgt_start, tgt_count, ae); + + // The result is index relative to from_index if substring was found, -1 otherwise. + // Generate code which will fold into cmove. + RegionNode* region = new RegionNode(3); + Node* phi = new PhiNode(region, TypeInt::INT); + + Node* cmp = _gvn.transform(new CmpINode(result, intcon(0))); + Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::lt)); + + Node* if_lt = generate_slow_guard(bol, NULL); + if (if_lt != NULL) { + // result == -1 + phi->init_req(2, result); + region->init_req(2, if_lt); + } + if (!stopped()) { + result = _gvn.transform(new AddINode(result, from_index)); + phi->init_req(1, result); + region->init_req(1, control()); + } + + set_control(_gvn.transform(region)); + record_for_igvn(region); + set_result(_gvn.transform(phi)); + + return true; +} + +//-----------------------------inline_string_indexOfChar----------------------- +bool LibraryCallKit::inline_string_indexOfChar() { + if (!Matcher::has_match_rule(Op_StrIndexOfChar) || !(UseSSE > 4)) { + return false; + } + assert(callee()->signature()->size() == 4, "String.indexOfChar() has 4 arguments"); + Node* src = argument(0); // byte[] + Node* tgt = argument(1); // tgt is int ch + Node* from_index = argument(2); + Node* max = argument(3); + + Node* src_offset = _gvn.transform(new LShiftINode(from_index, intcon(1))); + Node* src_start = array_element_address(src, src_offset, T_BYTE); + + Node* src_count = _gvn.transform(new SubINode(max, from_index)); + + RegionNode* region = new RegionNode(3); + Node* phi = new PhiNode(region, TypeInt::INT); + + Node* result = new StrIndexOfCharNode(control(), memory(TypeAryPtr::BYTES), src_start, src_count, tgt, StrIntrinsicNode::none); + C->set_has_split_ifs(true); // Has chance for split-if optimization + _gvn.transform(result); + + Node* cmp = _gvn.transform(new CmpINode(result, intcon(0))); + Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::lt)); + + Node* if_lt = generate_slow_guard(bol, NULL); + if (if_lt != NULL) { + // result == -1 + phi->init_req(2, result); + region->init_req(2, if_lt); + } + if (!stopped()) { + result = _gvn.transform(new AddINode(result, from_index)); + phi->init_req(1, result); + region->init_req(1, control()); + } + set_control(_gvn.transform(region)); + record_for_igvn(region); + set_result(_gvn.transform(phi)); + + return true; +} +//---------------------------inline_string_copy--------------------- +// compressIt == true --> generate a compressed copy operation (compress char[]/byte[] to byte[]) +// int StringUTF16.compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) +// int StringUTF16.compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) +// compressIt == false --> generate an inflated copy operation (inflate byte[] to char[]/byte[]) +// void StringLatin1.inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) +// void StringLatin1.inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) +bool LibraryCallKit::inline_string_copy(bool compress) { + int nargs = 5; // 2 oops, 3 ints + assert(callee()->signature()->size() == nargs, "string copy has 5 arguments"); + + Node* src = argument(0); + Node* src_offset = argument(1); + Node* dst = argument(2); + Node* dst_offset = argument(3); + Node* length = argument(4); + + // Check for allocation before we add nodes that would confuse + // tightly_coupled_allocation() + AllocateArrayNode* alloc = tightly_coupled_allocation(dst, NULL); + + // Figure out the size and type of the elements we will be copying. + const Type* src_type = src->Value(&_gvn); + const Type* dst_type = dst->Value(&_gvn); + BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + assert((compress && dst_elem == T_BYTE && (src_elem == T_BYTE || src_elem == T_CHAR)) || + (!compress && src_elem == T_BYTE && (dst_elem == T_BYTE || dst_elem == T_CHAR)), + "Unsupported array types for inline_string_copy"); + + // Convert char[] offsets to byte[] offsets + if (compress && src_elem == T_BYTE) { + src_offset = _gvn.transform(new LShiftINode(src_offset, intcon(1))); + } else if (!compress && dst_elem == T_BYTE) { + dst_offset = _gvn.transform(new LShiftINode(dst_offset, intcon(1))); + } + + Node* src_start = array_element_address(src, src_offset, src_elem); + Node* dst_start = array_element_address(dst, dst_offset, dst_elem); + // 'src_start' points to src array + scaled offset + // 'dst_start' points to dst array + scaled offset + Node* count = NULL; + if (compress) { + count = compress_string(src_start, dst_start, length); + } else { + inflate_string(src_start, dst_start, length); + } + + if (alloc != NULL) { + if (alloc->maybe_set_complete(&_gvn)) { + // "You break it, you buy it." + InitializeNode* init = alloc->initialization(); + assert(init->is_complete(), "we just did this"); + init->set_complete_with_arraycopy(); + assert(dst->is_CheckCastPP(), "sanity"); + assert(dst->in(0)->in(0) == init, "dest pinned"); + } + // Do not let stores that initialize this object be reordered with + // a subsequent store that would make this object accessible by + // other threads. + // Record what AllocateNode this StoreStore protects so that + // escape analysis can go from the MemBarStoreStoreNode to the + // AllocateNode and eliminate the MemBarStoreStoreNode if possible + // based on the escape status of the AllocateNode. + insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); + } + if (compress) { + set_result(_gvn.transform(count)); + } + return true; +} + +#ifdef _LP64 +#define XTOP ,top() /*additional argument*/ +#else //_LP64 +#define XTOP /*no additional argument*/ +#endif //_LP64 + +//------------------------inline_string_toBytesU-------------------------- +// public static byte[] StringUTF16.toBytes(char[] value, int off, int len) +bool LibraryCallKit::inline_string_toBytesU() { + // Get the arguments. + Node* value = argument(0); + Node* offset = argument(1); + Node* length = argument(2); + + Node* newcopy = NULL; + + // Set the original stack and the reexecute bit for the interpreter to reexecute + // the bytecode that invokes StringUTF16.toBytes() if deoptimization happens. + { PreserveReexecuteState preexecs(this); + jvms()->set_should_reexecute(true); + + // Check if a null path was taken unconditionally. + value = null_check(value); + + RegionNode* bailout = new RegionNode(1); + record_for_igvn(bailout); + + // Make sure that resulting byte[] length does not overflow Integer.MAX_VALUE + generate_negative_guard(length, bailout); + generate_limit_guard(length, intcon(0), intcon(max_jint/2), bailout); + + if (bailout->req() > 1) { + PreserveJVMState pjvms(this); + set_control(_gvn.transform(bailout)); + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_maybe_recompile); + } + if (stopped()) return true; + + // Range checks are done by caller. + + Node* size = _gvn.transform(new LShiftINode(length, intcon(1))); + Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_BYTE))); + newcopy = new_array(klass_node, size, 0); // no arguments to push + AllocateArrayNode* alloc = tightly_coupled_allocation(newcopy, NULL); + + // Calculate starting addresses. + Node* src_start = array_element_address(value, offset, T_CHAR); + Node* dst_start = basic_plus_adr(newcopy, arrayOopDesc::base_offset_in_bytes(T_BYTE)); + + // Check if src array address is aligned to HeapWordSize (dst is always aligned) + const TypeInt* toffset = gvn().type(offset)->is_int(); + bool aligned = toffset->is_con() && ((toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); + + // Figure out which arraycopy runtime method to call (disjoint, uninitialized). + const char* copyfunc_name = "arraycopy"; + address copyfunc_addr = StubRoutines::select_arraycopy_function(T_CHAR, aligned, true, copyfunc_name, true); + Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::fast_arraycopy_Type(), + copyfunc_addr, copyfunc_name, TypeRawPtr::BOTTOM, + src_start, dst_start, ConvI2X(length) XTOP); + // Do not let reads from the cloned object float above the arraycopy. + if (alloc != NULL) { + if (alloc->maybe_set_complete(&_gvn)) { + // "You break it, you buy it." + InitializeNode* init = alloc->initialization(); + assert(init->is_complete(), "we just did this"); + init->set_complete_with_arraycopy(); + assert(newcopy->is_CheckCastPP(), "sanity"); + assert(newcopy->in(0)->in(0) == init, "dest pinned"); + } + // Do not let stores that initialize this object be reordered with + // a subsequent store that would make this object accessible by + // other threads. + // Record what AllocateNode this StoreStore protects so that + // escape analysis can go from the MemBarStoreStoreNode to the + // AllocateNode and eliminate the MemBarStoreStoreNode if possible + // based on the escape status of the AllocateNode. + insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); + } else { + insert_mem_bar(Op_MemBarCPUOrder); + } + } // original reexecute is set back here + + C->set_has_split_ifs(true); // Has chance for split-if optimization + if (!stopped()) { + set_result(newcopy); + } + return true; +} + +//------------------------inline_string_getCharsU-------------------------- +// public void StringUTF16.getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) +bool LibraryCallKit::inline_string_getCharsU() { + if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; + + // Get the arguments. + Node* value = argument(0); + Node* src_begin = argument(1); + Node* src_end = argument(2); // exclusive offset (i < src_end) + Node* dst = argument(3); + Node* dst_begin = argument(4); + + // Check for allocation before we add nodes that would confuse + // tightly_coupled_allocation() + AllocateArrayNode* alloc = tightly_coupled_allocation(dst, NULL); + + // Check if a null path was taken unconditionally. + value = null_check(value); + dst = null_check(dst); + if (stopped()) { + return true; + } + + // Range checks are done by caller. + + // Get length and convert char[] offset to byte[] offset + Node* length = _gvn.transform(new SubINode(src_end, src_begin)); + src_begin = _gvn.transform(new LShiftINode(src_begin, intcon(1))); + + if (!stopped()) { + // Calculate starting addresses. + Node* src_start = array_element_address(value, src_begin, T_BYTE); + Node* dst_start = array_element_address(dst, dst_begin, T_CHAR); + + // Check if array addresses are aligned to HeapWordSize + const TypeInt* tsrc = gvn().type(src_begin)->is_int(); + const TypeInt* tdst = gvn().type(dst_begin)->is_int(); + bool aligned = tsrc->is_con() && ((tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) && + tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); + + // Figure out which arraycopy runtime method to call (disjoint, uninitialized). + const char* copyfunc_name = "arraycopy"; + address copyfunc_addr = StubRoutines::select_arraycopy_function(T_CHAR, aligned, true, copyfunc_name, true); + Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::fast_arraycopy_Type(), + copyfunc_addr, copyfunc_name, TypeRawPtr::BOTTOM, + src_start, dst_start, ConvI2X(length) XTOP); + // Do not let reads from the cloned object float above the arraycopy. + if (alloc != NULL) { + if (alloc->maybe_set_complete(&_gvn)) { + // "You break it, you buy it." + InitializeNode* init = alloc->initialization(); + assert(init->is_complete(), "we just did this"); + init->set_complete_with_arraycopy(); + assert(dst->is_CheckCastPP(), "sanity"); + assert(dst->in(0)->in(0) == init, "dest pinned"); + } + // Do not let stores that initialize this object be reordered with + // a subsequent store that would make this object accessible by + // other threads. + // Record what AllocateNode this StoreStore protects so that + // escape analysis can go from the MemBarStoreStoreNode to the + // AllocateNode and eliminate the MemBarStoreStoreNode if possible + // based on the escape status of the AllocateNode. + insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); + } else { + insert_mem_bar(Op_MemBarCPUOrder); + } + } + + C->set_has_split_ifs(true); // Has chance for split-if optimization + return true; +} + +//----------------------inline_string_char_access---------------------------- +// Store/Load char to/from byte[] array. +// static void StringUTF16.putChar(byte[] val, int index, int c) +// static char StringUTF16.getChar(byte[] val, int index) +bool LibraryCallKit::inline_string_char_access(bool is_store) { + Node* value = argument(0); + Node* index = argument(1); + Node* ch = is_store ? argument(2) : NULL; + + // This intrinsic accesses byte[] array as char[] array. Computing the offsets + // correctly requires matched array shapes. + assert (arrayOopDesc::base_offset_in_bytes(T_CHAR) == arrayOopDesc::base_offset_in_bytes(T_BYTE), + "sanity: byte[] and char[] bases agree"); + assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2, + "sanity: byte[] and char[] scales agree"); + + Node* adr = array_element_address(value, index, T_CHAR); + if (is_store) { + (void) store_to_memory(control(), adr, ch, T_CHAR, TypeAryPtr::BYTES, MemNode::unordered); + } else { + ch = make_load(control(), adr, TypeInt::CHAR, T_CHAR, MemNode::unordered); + set_result(ch); } - set_result(result); return true; } @@ -1365,7 +1476,7 @@ Node* LibraryCallKit::round_double_node(Node* n) { // public static double Math.log10(double) bool LibraryCallKit::inline_math(vmIntrinsics::ID id) { Node* arg = round_double_node(argument(0)); - Node* n; + Node* n = NULL; switch (id) { case vmIntrinsics::_dabs: n = new AbsDNode( arg); break; case vmIntrinsics::_dsqrt: n = new SqrtDNode(C, control(), arg); break; @@ -2110,7 +2221,7 @@ inline Node* LibraryCallKit::make_unsafe_address(Node* base, Node* offset) { // inline long Long.reverseBytes(long) bool LibraryCallKit::inline_number_methods(vmIntrinsics::ID id) { Node* arg = argument(0); - Node* n; + Node* n = NULL; switch (id) { case vmIntrinsics::_numberOfLeadingZeros_i: n = new CountLeadingZerosINode( arg); break; case vmIntrinsics::_numberOfLeadingZeros_l: n = new CountLeadingZerosLNode( arg); break; @@ -2650,7 +2761,7 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind // For now, we handle only those cases that actually exist: ints, // longs, and Object. Adding others should be straightforward. - Node* load_store; + Node* load_store = NULL; switch(type) { case T_INT: if (kind == LS_xadd) { @@ -2781,9 +2892,9 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind } //----------------------------inline_unsafe_ordered_store---------------------- -// public native void sun.misc.Unsafe.putOrderedObject(Object o, long offset, Object x); -// public native void sun.misc.Unsafe.putOrderedInt(Object o, long offset, int x); -// public native void sun.misc.Unsafe.putOrderedLong(Object o, long offset, long x); +// public native void Unsafe.putOrderedObject(Object o, long offset, Object x); +// public native void Unsafe.putOrderedInt(Object o, long offset, int x); +// public native void Unsafe.putOrderedLong(Object o, long offset, long x); bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { // This is another variant of inline_unsafe_access, differing in // that it always issues store-store ("release") barrier and ensures @@ -2877,7 +2988,7 @@ bool LibraryCallKit::klass_needs_init_guard(Node* kls) { } //----------------------------inline_unsafe_allocate--------------------------- -// public native Object sun.misc.Unsafe.allocateInstance(Class cls); +// public native Object Unsafe.allocateInstance(Class cls); bool LibraryCallKit::inline_unsafe_allocate() { if (callee()->is_static()) return false; // caller must have the capability! @@ -3656,7 +3767,7 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { Node* end = is_copyOfRange? argument(2): argument(1); Node* array_type_mirror = is_copyOfRange? argument(3): argument(2); - Node* newcopy; + Node* newcopy = NULL; // Set the original stack and the reexecute bit for the interpreter to reexecute // the bytecode that invokes Arrays.copyOf if deoptimization happens. @@ -4091,7 +4202,7 @@ bool LibraryCallKit::inline_native_Reflection_getCallerClass() { bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { Node* arg = argument(0); - Node* result; + Node* result = NULL; switch (id) { case vmIntrinsics::_floatToRawIntBits: result = new MoveF2INode(arg); break; @@ -4189,14 +4300,8 @@ bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { return true; } -#ifdef _LP64 -#define XTOP ,top() /*additional argument*/ -#else //_LP64 -#define XTOP /*no additional argument*/ -#endif //_LP64 - //----------------------inline_unsafe_copyMemory------------------------- -// public native void sun.misc.Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); +// public native void Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); bool LibraryCallKit::inline_unsafe_copyMemory() { if (callee()->is_static()) return false; // caller must have the capability! null_check_receiver(); // null-check receiver @@ -5003,10 +5108,11 @@ bool LibraryCallKit::inline_encodeISOArray() { // Figure out the size and type of the elements we will be copying. BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); - if (src_elem != T_CHAR || dst_elem != T_BYTE) { + if (!((src_elem == T_CHAR) || (src_elem== T_BYTE)) || dst_elem != T_BYTE) { return false; } - Node* src_start = array_element_address(src, src_offset, src_elem); + + Node* src_start = array_element_address(src, src_offset, T_CHAR); Node* dst_start = array_element_address(dst, dst_offset, dst_elem); // 'src_start' points to src array + scaled offset // 'dst_start' points to dst array + scaled offset @@ -5124,7 +5230,7 @@ bool LibraryCallKit::inline_multiplyToLen() { //-------------inline_squareToLen------------------------------------ bool LibraryCallKit::inline_squareToLen() { - assert(UseSquareToLenIntrinsic, "not implementated on this platform"); + assert(UseSquareToLenIntrinsic, "not implemented on this platform"); address stubAddr = StubRoutines::squareToLen(); if (stubAddr == NULL) { @@ -5170,7 +5276,7 @@ bool LibraryCallKit::inline_squareToLen() { //-------------inline_mulAdd------------------------------------------ bool LibraryCallKit::inline_mulAdd() { - assert(UseMulAddIntrinsic, "not implementated on this platform"); + assert(UseMulAddIntrinsic, "not implemented on this platform"); address stubAddr = StubRoutines::mulAdd(); if (stubAddr == NULL) { @@ -5720,7 +5826,7 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * field //------------------------------inline_aescrypt_Block----------------------- bool LibraryCallKit::inline_aescrypt_Block(vmIntrinsics::ID id) { - address stubAddr; + address stubAddr = NULL; const char *stubName; assert(UseAES, "need AES instruction support"); @@ -5786,8 +5892,8 @@ bool LibraryCallKit::inline_aescrypt_Block(vmIntrinsics::ID id) { //------------------------------inline_cipherBlockChaining_AESCrypt----------------------- bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) { - address stubAddr; - const char *stubName; + address stubAddr = NULL; + const char *stubName = NULL; assert(UseAES, "need AES instruction support"); diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index 02153bf31e6..735a00dd1a1 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -622,8 +622,10 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const { case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_StrIndexOfChar: case Op_EncodeISOArray: - case Op_AryEq: { + case Op_AryEq: + case Op_HasNegatives: { return false; } #if INCLUDE_RTM_OPT @@ -741,8 +743,10 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) { case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_StrIndexOfChar: case Op_EncodeISOArray: - case Op_AryEq: { + case Op_AryEq: + case Op_HasNegatives: { // Do not unroll a loop with String intrinsics code. // String intrinsics are large and have loops. return false; diff --git a/hotspot/src/share/vm/opto/loopnode.cpp b/hotspot/src/share/vm/opto/loopnode.cpp index 9c09c888f2c..eb09d62d23a 100644 --- a/hotspot/src/share/vm/opto/loopnode.cpp +++ b/hotspot/src/share/vm/opto/loopnode.cpp @@ -3494,7 +3494,9 @@ void PhaseIdealLoop::build_loop_late_post( Node *n ) { case Op_StrComp: // Does a bunch of load-like effects case Op_StrEquals: case Op_StrIndexOf: + case Op_StrIndexOfChar: case Op_AryEq: + case Op_HasNegatives: pinned = false; } if( pinned ) { diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 783ba1d3eeb..bd5ceaa9b7a 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -379,13 +379,25 @@ static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_me if (mem->is_LoadStore()) { adr = mem->in(MemNode::Address); } else { - assert(mem->Opcode() == Op_EncodeISOArray, "sanity"); + assert(mem->Opcode() == Op_EncodeISOArray || + mem->Opcode() == Op_StrCompressedCopy, "sanity"); adr = mem->in(3); // Destination array } const TypePtr* atype = adr->bottom_type()->is_ptr(); int adr_idx = phase->C->get_alias_index(atype); if (adr_idx == alias_idx) { - assert(false, "Object is not scalar replaceable if a LoadStore node access its field"); + DEBUG_ONLY(mem->dump();) + assert(false, "Object is not scalar replaceable if a LoadStore node accesses its field"); + return NULL; + } + mem = mem->in(MemNode::Memory); + } else if (mem->Opcode() == Op_StrInflatedCopy) { + Node* adr = mem->in(3); // Destination array + const TypePtr* atype = adr->bottom_type()->is_ptr(); + int adr_idx = phase->C->get_alias_index(atype); + if (adr_idx == alias_idx) { + DEBUG_ONLY(mem->dump();) + assert(false, "Object is not scalar replaceable if a StrInflatedCopy node accesses its field"); return NULL; } mem = mem->in(MemNode::Memory); @@ -516,8 +528,10 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type * } values.at_put(j, val); } else if (val->Opcode() == Op_SCMemProj) { - assert(val->in(0)->is_LoadStore() || val->in(0)->Opcode() == Op_EncodeISOArray, "sanity"); - assert(false, "Object is not scalar replaceable if a LoadStore node access its field"); + assert(val->in(0)->is_LoadStore() || + val->in(0)->Opcode() == Op_EncodeISOArray || + val->in(0)->Opcode() == Op_StrCompressedCopy, "sanity"); + assert(false, "Object is not scalar replaceable if a LoadStore node accesses its field"); return NULL; } else if (val->is_ArrayCopy()) { Node* res = make_arraycopy_load(val->as_ArrayCopy(), offset, val->in(0), ft, phi_type, alloc); @@ -779,10 +793,10 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray result_cast(); assert(res == NULL || res->is_CheckCastPP(), "unexpected AllocateNode result"); @@ -1305,10 +1319,10 @@ void PhaseMacroExpand::expand_allocate_common( // We need a Region and corresponding Phi's to merge the slow-path and fast-path results. // they will not be used if "always_slow" is set enum { slow_result_path = 1, fast_result_path = 2 }; - Node *result_region; - Node *result_phi_rawmem; - Node *result_phi_rawoop; - Node *result_phi_i_o; + Node *result_region = NULL; + Node *result_phi_rawmem = NULL; + Node *result_phi_rawoop = NULL; + Node *result_phi_i_o = NULL; // The initial slow comparison is a size check, the comparison // we want to do is a BoolTest::gt diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 684af2a82e4..117dd765ac8 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -936,9 +936,13 @@ static void match_alias_type(Compile* C, Node* n, Node* m) { case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_StrIndexOfChar: case Op_AryEq: + case Op_HasNegatives: case Op_MemBarVolatile: case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type? + case Op_StrInflatedCopy: + case Op_StrCompressedCopy: case Op_EncodeISOArray: nidx = Compile::AliasIdxTop; nat = NULL; @@ -2156,7 +2160,11 @@ void Matcher::find_shared( Node *n ) { case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_StrIndexOfChar: case Op_AryEq: + case Op_HasNegatives: + case Op_StrInflatedCopy: + case Op_StrCompressedCopy: case Op_EncodeISOArray: set_shared(n); // Force result into register (it will be anyways) break; @@ -2336,7 +2344,8 @@ void Matcher::find_shared( Node *n ) { n->del_req(3); break; } - case Op_StrEquals: { + case Op_StrEquals: + case Op_StrIndexOfChar: { Node *pair1 = new BinaryNode(n->in(2),n->in(3)); n->set_req(2,pair1); n->set_req(3,n->in(4)); @@ -2353,6 +2362,8 @@ void Matcher::find_shared( Node *n ) { n->del_req(4); break; } + case Op_StrCompressedCopy: + case Op_StrInflatedCopy: case Op_EncodeISOArray: { // Restructure into a binary tree for Matching. Node* pair = new BinaryNode(n->in(3), n->in(4)); diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 1abfede267b..b9b5838eca4 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -997,7 +997,7 @@ public: // "Acquire" - no following ref can move before (but earlier refs can // follow, like an early Load stalled in cache). Requires multi-cpu // visibility. Inserted independ of any load, as required -// for intrinsic sun.misc.Unsafe.loadFence(). +// for intrinsic Unsafe.loadFence(). class LoadFenceNode: public MemBarNode { public: LoadFenceNode(Compile* C, int alias_idx, Node* precedent) @@ -1018,7 +1018,7 @@ public: // "Release" - no earlier ref can move after (but later refs can move // up, like a speculative pipelined cache-hitting Load). Requires // multi-cpu visibility. Inserted independent of any store, as required -// for intrinsic sun.misc.Unsafe.storeFence(). +// for intrinsic Unsafe.storeFence(). class StoreFenceNode: public MemBarNode { public: StoreFenceNode(Compile* C, int alias_idx, Node* precedent) diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index 3a07d9f707c..99a3734ba46 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -108,7 +108,7 @@ Node *Parse::fetch_interpreter_state(int index, // Very similar to LoadNode::make, except we handle un-aligned longs and // doubles on Sparc. Intel can handle them just fine directly. - Node *l; + Node *l = NULL; switch (bt) { // Signature is flattened case T_INT: l = new LoadINode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInt::INT, MemNode::unordered); break; case T_FLOAT: l = new LoadFNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::FLOAT, MemNode::unordered); break; @@ -1903,7 +1903,7 @@ PhiNode *Parse::ensure_phi(int idx, bool nocreate) { // Now use a Phi here for merging assert(!nocreate, "Cannot build a phi for a block already parsed."); const JVMState* jvms = map->jvms(); - const Type* t; + const Type* t = NULL; if (jvms->is_loc(idx)) { t = block()->local_type_at(idx - jvms->locoff()); } else if (jvms->is_stk(idx)) { diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index b555ae00e9b..1ae727c105a 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -264,7 +264,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, JavaT // Scavenge and allocate an instance. oop result; - if (array_type->oop_is_typeArray()) { + if (array_type->is_typeArray_klass()) { // The oopFactory likes to work with the element type. // (We could bypass the oopFactory, since it doesn't add much value.) BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type(); @@ -302,7 +302,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len // Scavenge and allocate an instance. oop result; - assert(array_type->oop_is_typeArray(), "should be called only for type array"); + assert(array_type->is_typeArray_klass(), "should be called only for type array"); // The oopFactory likes to work with the element type. BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type(); result = oopFactory::new_typeArray_nozero(elem_type, len, THREAD); diff --git a/hotspot/src/share/vm/opto/split_if.cpp b/hotspot/src/share/vm/opto/split_if.cpp index 40a762b03a3..215832d68cf 100644 --- a/hotspot/src/share/vm/opto/split_if.cpp +++ b/hotspot/src/share/vm/opto/split_if.cpp @@ -451,8 +451,8 @@ void PhaseIdealLoop::do_split_if( Node *iff ) { // Replace both uses of 'new_iff' with Regions merging True/False // paths. This makes 'new_iff' go dead. - Node *old_false, *old_true; - Node *new_false, *new_true; + Node *old_false = NULL, *old_true = NULL; + Node *new_false = NULL, *new_true = NULL; for (DUIterator_Last j2min, j2 = iff->last_outs(j2min); j2 >= j2min; --j2) { Node *ifp = iff->last_out(j2); assert( ifp->Opcode() == Op_IfFalse || ifp->Opcode() == Op_IfTrue, "" ); diff --git a/hotspot/src/share/vm/opto/stringopts.cpp b/hotspot/src/share/vm/opto/stringopts.cpp index 4e67f5151fe..b11742f04b3 100644 --- a/hotspot/src/share/vm/opto/stringopts.cpp +++ b/hotspot/src/share/vm/opto/stringopts.cpp @@ -598,7 +598,7 @@ PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List*): } // Collect the types needed to talk about the various slices of memory - char_adr_idx = C->get_alias_index(TypeAryPtr::CHARS); + byte_adr_idx = C->get_alias_index(TypeAryPtr::BYTES); // For each locally allocated StringBuffer see if the usages can be // collapsed into a single String construction. @@ -1128,6 +1128,25 @@ Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) { } Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) { + if (arg->is_Con()) { + // Constant integer. Compute constant length using Integer.sizeTable + int arg_val = arg->get_int(); + int count = 1; + if (arg_val < 0) { + arg_val = -arg_val; + count++; + } + + ciArray* size_table = (ciArray*)size_table_field->constant_value().as_object(); + for (int i = 0; i < size_table->length(); i++) { + if (arg_val <= size_table->element_value(i).as_int()) { + count += i; + break; + } + } + return __ intcon(count); + } + RegionNode *final_merge = new RegionNode(3); kit.gvn().set_type(final_merge, Type::CONTROL); Node* final_size = new PhiNode(final_merge, TypeInt::INT); @@ -1212,77 +1231,34 @@ Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) { return final_size; } -void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, Node* start, Node* end) { - RegionNode *final_merge = new RegionNode(4); - kit.gvn().set_type(final_merge, Type::CONTROL); - Node *final_mem = PhiNode::make(final_merge, kit.memory(char_adr_idx), Type::MEMORY, TypeAryPtr::CHARS); - kit.gvn().set_type(final_mem, Type::MEMORY); - - // need to handle Integer.MIN_VALUE specially because negating doesn't make it positive - { - // i == MIN_VALUE - IfNode* iff = kit.create_and_map_if(kit.control(), - __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne), - PROB_FAIR, COUNT_UNKNOWN); - - Node* old_mem = kit.memory(char_adr_idx); - - kit.set_control(__ IfFalse(iff)); - if (kit.stopped()) { - // Statically not equal to MIN_VALUE so this path is dead - final_merge->init_req(3, kit.control()); - } else { - copy_string(kit, __ makecon(TypeInstPtr::make(C->env()->the_min_jint_string())), - char_array, start); - final_merge->init_req(3, kit.control()); - final_mem->init_req(3, kit.memory(char_adr_idx)); - } - - kit.set_control(__ IfTrue(iff)); - kit.set_memory(old_mem, char_adr_idx); - } - - - // Simplified version of Integer.getChars - - // int q, r; - // int charPos = index; - Node* charPos = end; - - // char sign = 0; - - Node* i = arg; - Node* sign = __ intcon(0); - +// Simplified version of Integer.getChars +void PhaseStringOpts::getChars(GraphKit& kit, Node* arg, Node* dst_array, BasicType bt, Node* end, Node* final_merge, Node* final_mem, int merge_index) { // if (i < 0) { // sign = '-'; // i = -i; // } - { - IfNode* iff = kit.create_and_map_if(kit.control(), - __ Bool(__ CmpI(arg, __ intcon(0)), BoolTest::lt), - PROB_FAIR, COUNT_UNKNOWN); + IfNode* iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(arg, __ intcon(0)), BoolTest::lt), + PROB_FAIR, COUNT_UNKNOWN); - RegionNode *merge = new RegionNode(3); - kit.gvn().set_type(merge, Type::CONTROL); - i = new PhiNode(merge, TypeInt::INT); - kit.gvn().set_type(i, TypeInt::INT); - sign = new PhiNode(merge, TypeInt::INT); - kit.gvn().set_type(sign, TypeInt::INT); + RegionNode* merge = new RegionNode(3); + kit.gvn().set_type(merge, Type::CONTROL); + Node* i = new PhiNode(merge, TypeInt::INT); + kit.gvn().set_type(i, TypeInt::INT); + Node* sign = new PhiNode(merge, TypeInt::INT); + kit.gvn().set_type(sign, TypeInt::INT); - merge->init_req(1, __ IfTrue(iff)); - i->init_req(1, __ SubI(__ intcon(0), arg)); - sign->init_req(1, __ intcon('-')); - merge->init_req(2, __ IfFalse(iff)); - i->init_req(2, arg); - sign->init_req(2, __ intcon(0)); + merge->init_req(1, __ IfTrue(iff)); + i->init_req(1, __ SubI(__ intcon(0), arg)); + sign->init_req(1, __ intcon('-')); + merge->init_req(2, __ IfFalse(iff)); + i->init_req(2, arg); + sign->init_req(2, __ intcon(0)); - kit.set_control(merge); + kit.set_control(merge); - C->record_for_igvn(merge); - C->record_for_igvn(i); - C->record_for_igvn(sign); - } + C->record_for_igvn(merge); + C->record_for_igvn(i); + C->record_for_igvn(sign); // for (;;) { // q = i / 10; @@ -1292,126 +1268,409 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N // if (i == 0) break; // } - { - // Add loop predicate first. - kit.add_predicate(); + // Add loop predicate first. + kit.add_predicate(); - RegionNode *head = new RegionNode(3); - head->init_req(1, kit.control()); - kit.gvn().set_type(head, Type::CONTROL); - Node *i_phi = new PhiNode(head, TypeInt::INT); - i_phi->init_req(1, i); - kit.gvn().set_type(i_phi, TypeInt::INT); - charPos = PhiNode::make(head, charPos); - kit.gvn().set_type(charPos, TypeInt::INT); - Node *mem = PhiNode::make(head, kit.memory(char_adr_idx), Type::MEMORY, TypeAryPtr::CHARS); - kit.gvn().set_type(mem, Type::MEMORY); - kit.set_control(head); - kit.set_memory(mem, char_adr_idx); + RegionNode* head = new RegionNode(3); + head->init_req(1, kit.control()); - Node* q = __ DivI(NULL, i_phi, __ intcon(10)); - Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)), - __ LShiftI(q, __ intcon(1)))); - Node* m1 = __ SubI(charPos, __ intcon(1)); - Node* ch = __ AddI(r, __ intcon('0')); + kit.gvn().set_type(head, Type::CONTROL); + Node* i_phi = new PhiNode(head, TypeInt::INT); + i_phi->init_req(1, i); + kit.gvn().set_type(i_phi, TypeInt::INT); + Node* charPos = new PhiNode(head, TypeInt::INT); + charPos->init_req(1, end); + kit.gvn().set_type(charPos, TypeInt::INT); + Node* mem = PhiNode::make(head, kit.memory(byte_adr_idx), Type::MEMORY, TypeAryPtr::BYTES); + kit.gvn().set_type(mem, Type::MEMORY); - Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR), - ch, T_CHAR, char_adr_idx, MemNode::unordered); + kit.set_control(head); + kit.set_memory(mem, byte_adr_idx); + Node* q = __ DivI(kit.null(), i_phi, __ intcon(10)); + Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)), + __ LShiftI(q, __ intcon(1)))); + Node* index = __ SubI(charPos, __ intcon((bt == T_BYTE) ? 1 : 2)); + Node* ch = __ AddI(r, __ intcon('0')); + Node* st = __ store_to_memory(kit.control(), kit.array_element_address(dst_array, index, T_BYTE), + ch, bt, byte_adr_idx, MemNode::unordered); - IfNode* iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne), - PROB_FAIR, COUNT_UNKNOWN); - Node* ne = __ IfTrue(iff); - Node* eq = __ IfFalse(iff); + iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne), + PROB_FAIR, COUNT_UNKNOWN); + Node* ne = __ IfTrue(iff); + Node* eq = __ IfFalse(iff); - head->init_req(2, ne); - mem->init_req(2, st); - i_phi->init_req(2, q); - charPos->init_req(2, m1); + head->init_req(2, ne); + mem->init_req(2, st); - charPos = m1; + i_phi->init_req(2, q); + charPos->init_req(2, index); + charPos = index; - kit.set_control(eq); - kit.set_memory(st, char_adr_idx); + kit.set_control(eq); + kit.set_memory(st, byte_adr_idx); - C->record_for_igvn(head); - C->record_for_igvn(mem); - C->record_for_igvn(i_phi); - C->record_for_igvn(charPos); - } + C->record_for_igvn(head); + C->record_for_igvn(mem); + C->record_for_igvn(i_phi); + C->record_for_igvn(charPos); - { - // if (sign != 0) { - // buf [--charPos] = sign; - // } - IfNode* iff = kit.create_and_map_if(kit.control(), - __ Bool(__ CmpI(sign, __ intcon(0)), BoolTest::ne), - PROB_FAIR, COUNT_UNKNOWN); + // if (sign != 0) { + // buf [--charPos] = sign; + // } + iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(sign, __ intcon(0)), BoolTest::ne), + PROB_FAIR, COUNT_UNKNOWN); - final_merge->init_req(2, __ IfFalse(iff)); - final_mem->init_req(2, kit.memory(char_adr_idx)); + final_merge->init_req(merge_index + 2, __ IfFalse(iff)); + final_mem->init_req(merge_index + 2, kit.memory(byte_adr_idx)); - kit.set_control(__ IfTrue(iff)); - if (kit.stopped()) { - final_merge->init_req(1, C->top()); - final_mem->init_req(1, C->top()); - } else { - Node* m1 = __ SubI(charPos, __ intcon(1)); - Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR), - sign, T_CHAR, char_adr_idx, MemNode::unordered); + kit.set_control(__ IfTrue(iff)); + if (kit.stopped()) { + final_merge->init_req(merge_index + 1, C->top()); + final_mem->init_req(merge_index + 1, C->top()); + } else { + Node* index = __ SubI(charPos, __ intcon((bt == T_BYTE) ? 1 : 2)); + st = __ store_to_memory(kit.control(), kit.array_element_address(dst_array, index, T_BYTE), + sign, bt, byte_adr_idx, MemNode::unordered); - final_merge->init_req(1, kit.control()); - final_mem->init_req(1, st); - } - - kit.set_control(final_merge); - kit.set_memory(final_mem, char_adr_idx); - - C->record_for_igvn(final_merge); - C->record_for_igvn(final_mem); + final_merge->init_req(merge_index + 1, kit.control()); + final_mem->init_req(merge_index + 1, st); } } +// Copy the characters representing arg into dst_array starting at start +Node* PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* dst_array, Node* dst_coder, Node* start, Node* size) { + bool dcon = dst_coder->is_Con(); + bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false; + Node* end = __ AddI(start, __ LShiftI(size, dst_coder)); -Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start) { - Node* string = str; - Node* offset = kit.load_String_offset(kit.control(), string); - Node* count = kit.load_String_length(kit.control(), string); - Node* value = kit.load_String_value (kit.control(), string); + // The final_merge node has 4 entries in case the encoding is known: + // (0) Control, (1) result w/ sign, (2) result w/o sign, (3) result for Integer.min_value + // or 6 entries in case the encoding is not known: + // (0) Control, (1) Latin1 w/ sign, (2) Latin1 w/o sign, (3) min_value, (4) UTF16 w/ sign, (5) UTF16 w/o sign + RegionNode* final_merge = new RegionNode(dcon ? 4 : 6); + kit.gvn().set_type(final_merge, Type::CONTROL); + + Node* final_mem = PhiNode::make(final_merge, kit.memory(byte_adr_idx), Type::MEMORY, TypeAryPtr::BYTES); + kit.gvn().set_type(final_mem, Type::MEMORY); + + // need to handle arg == Integer.MIN_VALUE specially because negating doesn't make it positive + IfNode* iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne), + PROB_FAIR, COUNT_UNKNOWN); + + Node* old_mem = kit.memory(byte_adr_idx); + + kit.set_control(__ IfFalse(iff)); + if (kit.stopped()) { + // Statically not equal to MIN_VALUE so this path is dead + final_merge->init_req(3, kit.control()); + } else { + copy_string(kit, __ makecon(TypeInstPtr::make(C->env()->the_min_jint_string())), + dst_array, dst_coder, start); + final_merge->init_req(3, kit.control()); + final_mem->init_req(3, kit.memory(byte_adr_idx)); + } + + kit.set_control(__ IfTrue(iff)); + kit.set_memory(old_mem, byte_adr_idx); + + if (!dcon) { + // Check encoding of destination + iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(dst_coder, __ intcon(0)), BoolTest::eq), + PROB_FAIR, COUNT_UNKNOWN); + old_mem = kit.memory(byte_adr_idx); + } + if (!dcon || dbyte) { + // Destination is Latin1, + if (!dcon) { + kit.set_control(__ IfTrue(iff)); + } + getChars(kit, arg, dst_array, T_BYTE, end, final_merge, final_mem); + } + if (!dcon || !dbyte) { + // Destination is UTF16 + int merge_index = 0; + if (!dcon) { + kit.set_control(__ IfFalse(iff)); + kit.set_memory(old_mem, byte_adr_idx); + merge_index = 3; // Account for Latin1 case + } + getChars(kit, arg, dst_array, T_CHAR, end, final_merge, final_mem, merge_index); + } + + // Final merge point for Latin1 and UTF16 case + kit.set_control(final_merge); + kit.set_memory(final_mem, byte_adr_idx); + + C->record_for_igvn(final_merge); + C->record_for_igvn(final_mem); + return end; +} + +// Copy 'count' bytes/chars from src_array to dst_array starting at index start +void PhaseStringOpts::arraycopy(GraphKit& kit, IdealKit& ideal, Node* src_array, Node* dst_array, BasicType elembt, Node* start, Node* count) { + assert(elembt == T_BYTE || elembt == T_CHAR, "Invalid type for arraycopy"); + + if (elembt == T_CHAR) { + // Get number of chars + count = __ RShiftI(count, __ intcon(1)); + } + + Node* extra = NULL; +#ifdef _LP64 + count = __ ConvI2L(count); + extra = C->top(); +#endif + + Node* src_ptr = __ array_element_address(src_array, __ intcon(0), T_BYTE); + Node* dst_ptr = __ array_element_address(dst_array, start, T_BYTE); + // Check if destination address is aligned to HeapWordSize + const TypeInt* tdst = __ gvn().type(start)->is_int(); + bool aligned = tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0); + // Figure out which arraycopy runtime method to call (disjoint, uninitialized). + const char* copyfunc_name = "arraycopy"; + address copyfunc_addr = StubRoutines::select_arraycopy_function(elembt, aligned, true, copyfunc_name, true); + ideal.make_leaf_call_no_fp(OptoRuntime::fast_arraycopy_Type(), copyfunc_addr, copyfunc_name, + TypeAryPtr::BYTES, src_ptr, dst_ptr, count, extra); +} + +#undef __ +#define __ ideal. + +// Copy contents of a Latin1 encoded string from src_array to dst_array +void PhaseStringOpts::copy_latin1_string(GraphKit& kit, IdealKit& ideal, Node* src_array, IdealVariable& count, + Node* dst_array, Node* dst_coder, Node* start) { + bool dcon = dst_coder->is_Con(); + bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false; + + if (!dcon) { + __ if_then(dst_coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1)); + } + if (!dcon || dbyte) { + // Destination is Latin1. Simply emit a byte arraycopy. + arraycopy(kit, ideal, src_array, dst_array, T_BYTE, start, __ value(count)); + } + if (!dcon) { + __ else_(); + } + if (!dcon || !dbyte) { + // Destination is UTF16. Inflate src_array into dst_array. + kit.sync_kit(ideal); + if (Matcher::match_rule_supported(Op_StrInflatedCopy)) { + // Use fast intrinsic + Node* src = kit.array_element_address(src_array, kit.intcon(0), T_BYTE); + Node* dst = kit.array_element_address(dst_array, start, T_BYTE); + kit.inflate_string(src, dst, __ value(count)); + } else { + // No intrinsic available, use slow method + kit.inflate_string_slow(src_array, dst_array, start, __ value(count)); + } + ideal.sync_kit(&kit); + // Multiply count by two since we now need two bytes per char + __ set(count, __ LShiftI(__ value(count), __ ConI(1))); + } + if (!dcon) { + __ end_if(); + } +} + +// Read two bytes from index and index+1 and convert them to a char +static jchar readChar(ciTypeArray* array, int index) { + int shift_high, shift_low; +#ifdef VM_LITTLE_ENDIAN + shift_high = 0; + shift_low = 8; +#else + shift_high = 8; + shift_low = 0; +#endif + + jchar b1 = ((jchar) array->byte_at(index)) & 0xff; + jchar b2 = ((jchar) array->byte_at(index+1)) & 0xff; + return (b1 << shift_high) | (b2 << shift_low); +} + +// Copy contents of constant src_array to dst_array by emitting individual stores +void PhaseStringOpts::copy_constant_string(GraphKit& kit, IdealKit& ideal, ciTypeArray* src_array, IdealVariable& count, + bool src_is_byte, Node* dst_array, Node* dst_coder, Node* start) { + bool dcon = dst_coder->is_Con(); + bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false; + int length = src_array->length(); + + if (!dcon) { + __ if_then(dst_coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1)); + } + if (!dcon || dbyte) { + // Destination is Latin1. Copy each byte of src_array into dst_array. + Node* index = start; + for (int i = 0; i < length; i++) { + Node* adr = kit.array_element_address(dst_array, index, T_BYTE); + Node* val = __ ConI(src_array->byte_at(i)); + __ store(__ ctrl(), adr, val, T_BYTE, byte_adr_idx, MemNode::unordered); + index = __ AddI(index, __ ConI(1)); + } + } + if (!dcon) { + __ else_(); + } + if (!dcon || !dbyte) { + // Destination is UTF16. Copy each char of src_array into dst_array. + Node* index = start; + for (int i = 0; i < length; i++) { + Node* adr = kit.array_element_address(dst_array, index, T_BYTE); + jchar val; + if (src_is_byte) { + val = src_array->byte_at(i) & 0xff; + } else { + val = readChar(src_array, i++); + } + __ store(__ ctrl(), adr, __ ConI(val), T_CHAR, byte_adr_idx, MemNode::unordered); + index = __ AddI(index, __ ConI(2)); + } + if (src_is_byte) { + // Multiply count by two since we now need two bytes per char + __ set(count, __ ConI(2 * length)); + } + } + if (!dcon) { + __ end_if(); + } +} + +// Compress copy contents of the byte/char String str into dst_array starting at index start. +Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* dst_array, Node* dst_coder, Node* start) { + Node* src_array = kit.load_String_value(kit.control(), str); + + IdealKit ideal(&kit, true, true); + IdealVariable count(ideal); __ declarations_done(); + + if (str->is_Con()) { + // Constant source string + const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr(); + ciTypeArray* src_array_type = t->const_oop()->as_type_array(); + + // Check encoding of constant string + bool src_is_byte = (get_constant_coder(kit, str) == java_lang_String::CODER_LATIN1); - // copy the contents - if (offset->is_Con() && count->is_Con() && value->is_Con() && count->get_int() < unroll_string_copy_length) { // For small constant strings just emit individual stores. // A length of 6 seems like a good space/speed tradeof. - int c = count->get_int(); - int o = offset->get_int(); - const TypeOopPtr* t = kit.gvn().type(value)->isa_oopptr(); - ciTypeArray* value_array = t->const_oop()->as_type_array(); - for (int e = 0; e < c; e++) { - __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR), - __ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx, - MemNode::unordered); - start = __ AddI(start, __ intcon(1)); + __ set(count, __ ConI(src_array_type->length())); + int src_len = src_array_type->length() / (src_is_byte ? 1 : 2); + if (src_len < unroll_string_copy_length) { + // Small constant string + copy_constant_string(kit, ideal, src_array_type, count, src_is_byte, dst_array, dst_coder, start); + } else if (src_is_byte) { + // Source is Latin1 + copy_latin1_string(kit, ideal, src_array, count, dst_array, dst_coder, start); + } else { + // Source is UTF16 (destination too). Simply emit a char arraycopy. + arraycopy(kit, ideal, src_array, dst_array, T_CHAR, start, __ value(count)); } } else { - Node* src_ptr = kit.array_element_address(value, offset, T_CHAR); - Node* dst_ptr = kit.array_element_address(char_array, start, T_CHAR); - Node* c = count; - Node* extra = NULL; -#ifdef _LP64 - c = __ ConvI2L(c); - extra = C->top(); -#endif - Node* call = kit.make_runtime_call(GraphKit::RC_LEAF|GraphKit::RC_NO_FP, - OptoRuntime::fast_arraycopy_Type(), - CAST_FROM_FN_PTR(address, StubRoutines::jshort_disjoint_arraycopy()), - "jshort_disjoint_arraycopy", TypeAryPtr::CHARS, - src_ptr, dst_ptr, c, extra); - start = __ AddI(start, count); + Node* size = kit.load_array_length(src_array); + __ set(count, size); + // Non-constant source string + if (CompactStrings) { + // Emit runtime check for coder + Node* coder = kit.load_String_coder(__ ctrl(), str); + __ if_then(coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1)); { + // Source is Latin1 + copy_latin1_string(kit, ideal, src_array, count, dst_array, dst_coder, start); + } __ else_(); + } + // Source is UTF16 (destination too). Simply emit a char arraycopy. + arraycopy(kit, ideal, src_array, dst_array, T_CHAR, start, __ value(count)); + + if (CompactStrings) { + __ end_if(); + } } - return start; + + // Finally sync IdealKit and GraphKit. + kit.sync_kit(ideal); + return __ AddI(start, __ value(count)); } +// Compress copy the char into dst_array at index start. +Node* PhaseStringOpts::copy_char(GraphKit& kit, Node* val, Node* dst_array, Node* dst_coder, Node* start) { + bool dcon = (dst_coder != NULL) && dst_coder->is_Con(); + bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false; + + IdealKit ideal(&kit, true, true); + IdealVariable end(ideal); __ declarations_done(); + Node* adr = kit.array_element_address(dst_array, start, T_BYTE); + if (!dcon){ + __ if_then(dst_coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1)); + } + if (!dcon || dbyte) { + // Destination is Latin1. Store a byte. + __ store(__ ctrl(), adr, val, T_BYTE, byte_adr_idx, MemNode::unordered); + __ set(end, __ AddI(start, __ ConI(1))); + } + if (!dcon) { + __ else_(); + } + if (!dcon || !dbyte) { + // Destination is UTF16. Store a char. + __ store(__ ctrl(), adr, val, T_CHAR, byte_adr_idx, MemNode::unordered); + __ set(end, __ AddI(start, __ ConI(2))); + } + if (!dcon) { + __ end_if(); + } + // Finally sync IdealKit and GraphKit. + kit.sync_kit(ideal); + return __ value(end); +} + +#undef __ +#define __ kit. + +// Allocate a byte array of specified length. +Node* PhaseStringOpts::allocate_byte_array(GraphKit& kit, IdealKit* ideal, Node* length) { + if (ideal != NULL) { + // Sync IdealKit and graphKit. + kit.sync_kit(*ideal); + } + Node* byte_array = NULL; + { + PreserveReexecuteState preexecs(&kit); + // The original jvms is for an allocation of either a String or + // StringBuffer so no stack adjustment is necessary for proper + // reexecution. If we deoptimize in the slow path the bytecode + // will be reexecuted and the char[] allocation will be thrown away. + kit.jvms()->set_should_reexecute(true); + byte_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_BYTE))), + length, 1); + } + + // Mark the allocation so that zeroing is skipped since the code + // below will overwrite the entire array + AllocateArrayNode* byte_alloc = AllocateArrayNode::Ideal_array_allocation(byte_array, _gvn); + byte_alloc->maybe_set_complete(_gvn); + + if (ideal != NULL) { + // Sync IdealKit and graphKit. + ideal->sync_kit(&kit); + } + return byte_array; +} + +jbyte PhaseStringOpts::get_constant_coder(GraphKit& kit, Node* str) { + assert(str->is_Con(), "String must be constant"); + const TypeOopPtr* str_type = kit.gvn().type(str)->isa_oopptr(); + ciInstance* str_instance = str_type->const_oop()->as_instance(); + jbyte coder = str_instance->field_value_by_offset(java_lang_String::coder_offset_in_bytes()).as_byte(); + assert(CompactStrings || (coder == java_lang_String::CODER_UTF16), "Strings must be UTF16 encoded"); + return coder; +} + +int PhaseStringOpts::get_constant_length(GraphKit& kit, Node* str) { + assert(str->is_Con(), "String must be constant"); + Node* src_array = kit.load_String_value(kit.control(), str); + const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr(); + return t->const_oop()->as_type_array()->length(); +} void PhaseStringOpts::replace_string_concat(StringConcat* sc) { // Log a little info about the transformation @@ -1445,7 +1704,6 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { jvms->set_map(map); map->ensure_stack(jvms, jvms->method()->max_stack()); - // disconnect all the old StringBuilder calls from the graph sc->eliminate_unneeded_control(); @@ -1473,7 +1731,17 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { // are need for the copying phase. Node* string_sizes = new Node(args); + Node* coder = __ intcon(0); Node* length = __ intcon(0); + // If at least one argument is UTF16 encoded, we can fix the encoding. + bool coder_fixed = false; + + if (!CompactStrings) { + // Fix encoding of result string to UTF16 + coder_fixed = true; + coder = __ intcon(java_lang_String::CODER_UTF16); + } + for (int argi = 0; argi < sc->num_arguments(); argi++) { Node* arg = sc->argument(argi); switch (sc->mode(argi)) { @@ -1491,7 +1759,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { const Type* type = kit.gvn().type(arg); assert(type != TypePtr::NULL_PTR, "missing check"); if (!type->higher_equal(TypeInstPtr::NOTNULL)) { - // Null check with uncommont trap since + // Null check with uncommon trap since // StringBuilder(null) throws exception. // Use special uncommon trap instead of // calling normal do_null_check(). @@ -1509,11 +1777,13 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { case StringConcat::StringMode: { const Type* type = kit.gvn().type(arg); Node* count = NULL; + Node* arg_coder = NULL; if (type == TypePtr::NULL_PTR) { // replace the argument with the null checked version arg = null_string; sc->set_argument(argi, arg); count = kit.load_String_length(kit.control(), arg); + arg_coder = kit.load_String_coder(kit.control(), arg); } else if (!type->higher_equal(TypeInstPtr::NOTNULL)) { // s = s != null ? s : "null"; // length = length + (s.count - s.offset); @@ -1537,11 +1807,32 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { arg = phi; sc->set_argument(argi, arg); count = kit.load_String_length(kit.control(), arg); + arg_coder = kit.load_String_coder(kit.control(), arg); } else { // A corresponding nullcheck will be connected during IGVN MemNode::Ideal_common_DU_postCCP // kit.control might be a different test, that can be hoisted above the actual nullcheck // in case, that the control input is not null, Ideal_common_DU_postCCP will not look for a nullcheck. count = kit.load_String_length(NULL, arg); + arg_coder = kit.load_String_coder(NULL, arg); + } + if (arg->is_Con()) { + // Constant string. Get constant coder and length. + jbyte const_coder = get_constant_coder(kit, arg); + int const_length = get_constant_length(kit, arg); + if (const_coder == java_lang_String::CODER_LATIN1) { + // Can be latin1 encoded + arg_coder = __ intcon(const_coder); + count = __ intcon(const_length); + } else { + // Found UTF16 encoded string. Fix result array encoding to UTF16. + coder_fixed = true; + coder = __ intcon(const_coder); + count = __ intcon(const_length / 2); + } + } + + if (!coder_fixed) { + coder = __ OrI(coder, arg_coder); } length = __ AddI(length, count); string_sizes->init_req(argi, NULL); @@ -1549,6 +1840,34 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { } case StringConcat::CharMode: { // one character only + const TypeInt* t = kit.gvn().type(arg)->is_int(); + if (!coder_fixed && t->is_con()) { + // Constant char + if (t->get_con() <= 255) { + // Can be latin1 encoded + coder = __ OrI(coder, __ intcon(java_lang_String::CODER_LATIN1)); + } else { + // Must be UTF16 encoded. Fix result array encoding to UTF16. + coder_fixed = true; + coder = __ intcon(java_lang_String::CODER_UTF16); + } + } else if (!coder_fixed) { + // Not constant +#undef __ +#define __ ideal. + IdealKit ideal(&kit, true, true); + IdealVariable char_coder(ideal); __ declarations_done(); + // Check if character can be latin1 encoded + __ if_then(arg, BoolTest::le, __ ConI(0xFF)); + __ set(char_coder, __ ConI(java_lang_String::CODER_LATIN1)); + __ else_(); + __ set(char_coder, __ ConI(java_lang_String::CODER_UTF16)); + __ end_if(); + kit.sync_kit(ideal); + coder = __ OrI(coder, __ value(char_coder)); +#undef __ +#define __ kit. + } length = __ AddI(length, __ intcon(1)); break; } @@ -1576,54 +1895,37 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { Node* result; if (!kit.stopped()) { - Node* char_array = NULL; + assert(CompactStrings || (coder->is_Con() && coder->get_int() == java_lang_String::CODER_UTF16), + "Result string must be UTF16 encoded if CompactStrings is disabled"); + + Node* dst_array = NULL; if (sc->num_arguments() == 1 && - (sc->mode(0) == StringConcat::StringMode || - sc->mode(0) == StringConcat::StringNullCheckMode)) { + (sc->mode(0) == StringConcat::StringMode || + sc->mode(0) == StringConcat::StringNullCheckMode)) { // Handle the case when there is only a single String argument. // In this case, we can just pull the value from the String itself. - char_array = kit.load_String_value(kit.control(), sc->argument(0)); + dst_array = kit.load_String_value(kit.control(), sc->argument(0)); } else { - // length now contains the number of characters needed for the - // char[] so create a new AllocateArray for the char[] - { - PreserveReexecuteState preexecs(&kit); - // The original jvms is for an allocation of either a String or - // StringBuffer so no stack adjustment is necessary for proper - // reexecution. If we deoptimize in the slow path the bytecode - // will be reexecuted and the char[] allocation will be thrown away. - kit.jvms()->set_should_reexecute(true); - char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))), - length, 1); - } + // Allocate destination byte array according to coder + dst_array = allocate_byte_array(kit, NULL, __ LShiftI(length, coder)); - // Mark the allocation so that zeroing is skipped since the code - // below will overwrite the entire array - AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn); - char_alloc->maybe_set_complete(_gvn); - - // Now copy the string representations into the final char[] + // Now copy the string representations into the final byte[] Node* start = __ intcon(0); for (int argi = 0; argi < sc->num_arguments(); argi++) { Node* arg = sc->argument(argi); switch (sc->mode(argi)) { case StringConcat::IntMode: { - Node* end = __ AddI(start, string_sizes->in(argi)); - // getChars words backwards so pass the ending point as well as the start - int_getChars(kit, arg, char_array, start, end); - start = end; + start = int_getChars(kit, arg, dst_array, coder, start, string_sizes->in(argi)); break; } case StringConcat::StringNullCheckMode: case StringConcat::StringMode: { - start = copy_string(kit, arg, char_array, start); + start = copy_string(kit, arg, dst_array, coder, start); break; } case StringConcat::CharMode: { - __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR), - arg, T_CHAR, char_adr_idx, MemNode::unordered); - start = __ AddI(start, __ intcon(1)); - break; + start = copy_char(kit, arg, dst_array, coder, start); + break; } default: ShouldNotReachHere(); @@ -1642,12 +1944,9 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { result = kit.new_instance(__ makecon(TypeKlassPtr::make(C->env()->String_klass()))); } - // Intialize the string - if (java_lang_String::has_offset_field()) { - kit.store_String_offset(kit.control(), result, __ intcon(0)); - kit.store_String_length(kit.control(), result, length); - } - kit.store_String_value(kit.control(), result, char_array); + // Initialize the string + kit.store_String_value(kit.control(), result, dst_array); + kit.store_String_coder(kit.control(), result, coder); } else { result = C->top(); } diff --git a/hotspot/src/share/vm/opto/stringopts.hpp b/hotspot/src/share/vm/opto/stringopts.hpp index 0fb1ed70f64..d50616b3329 100644 --- a/hotspot/src/share/vm/opto/stringopts.hpp +++ b/hotspot/src/share/vm/opto/stringopts.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, 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 @@ -29,6 +29,7 @@ #include "opto/phaseX.hpp" class StringConcat; +class IdealVariable; class PhaseStringOpts : public Phase { friend class StringConcat; @@ -40,7 +41,7 @@ class PhaseStringOpts : public Phase { Unique_Node_List dead_worklist; // Memory slices needed for code gen - int char_adr_idx; + int byte_adr_idx; // Integer.sizeTable - used for int to String conversion ciField* size_table_field; @@ -64,11 +65,37 @@ class PhaseStringOpts : public Phase { // Compute the number of characters required to represent the int value Node* int_stringSize(GraphKit& kit, Node* value); - // Copy the characters representing value into char_array starting at start - void int_getChars(GraphKit& kit, Node* value, Node* char_array, Node* start, Node* end); + // Simplified version of Integer.getChars + void getChars(GraphKit& kit, Node* arg, Node* dst_array, BasicType bt, Node* end, Node* final_merge, Node* final_mem, int merge_index = 0); - // Copy of the contents of the String str into char_array starting at index start. - Node* copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start); + // Copy the characters representing arg into dst_array starting at start + Node* int_getChars(GraphKit& kit, Node* arg, Node* dst_array, Node* dst_coder, Node* start, Node* size); + + // Copy contents of the String str into dst_array starting at index start. + Node* copy_string(GraphKit& kit, Node* str, Node* dst_array, Node* dst_coder, Node* start); + + // Copy 'count' bytes/chars from src_array to dst_array starting at index start + void arraycopy(GraphKit& kit, IdealKit& ideal, Node* src_array, Node* dst_array, BasicType elembt, Node* start, Node* count); + + // Copy contents of constant src_array to dst_array by emitting individual stores + void copy_constant_string(GraphKit& kit, IdealKit& ideal, ciTypeArray* src_array, IdealVariable& count, + bool src_is_byte, Node* dst_array, Node* dst_coder, Node* start); + + // Copy contents of a Latin1 encoded string from src_array to dst_array + void copy_latin1_string(GraphKit& kit, IdealKit& ideal, Node* src_array, IdealVariable& count, + Node* dst_array, Node* dst_coder, Node* start); + + // Copy the char into dst_array at index start. + Node* copy_char(GraphKit& kit, Node* val, Node* dst_array, Node* dst_coder, Node* start); + + // Allocate a byte array of specified length. + Node* allocate_byte_array(GraphKit& kit, IdealKit* ideal, Node* length); + + // Returns the coder of a constant string + jbyte get_constant_coder(GraphKit& kit, Node* str); + + // Returns the length of a constant string + int get_constant_length(GraphKit& kit, Node* str); // Clean up any leftover nodes void record_dead_node(Node* node); diff --git a/hotspot/src/share/vm/opto/superword.cpp b/hotspot/src/share/vm/opto/superword.cpp index 1b37e0adcee..ba6e8192746 100644 --- a/hotspot/src/share/vm/opto/superword.cpp +++ b/hotspot/src/share/vm/opto/superword.cpp @@ -4001,7 +4001,7 @@ Node* SuperWord::last_node(Node* nd) { } int SuperWord::mark_generations() { - Node *ii_err = 0, *tail_err; + Node *ii_err = NULL, *tail_err = NULL; for (int i = 0; i < _mem_slice_head.length(); i++) { Node* phi = _mem_slice_head.at(i); assert(phi->is_Phi(), "must be phi"); diff --git a/hotspot/src/share/vm/precompiled/precompiled.hpp b/hotspot/src/share/vm/precompiled/precompiled.hpp index 70e72ab514f..cb729d28212 100644 --- a/hotspot/src/share/vm/precompiled/precompiled.hpp +++ b/hotspot/src/share/vm/precompiled/precompiled.hpp @@ -304,7 +304,7 @@ # include "gc/g1/g1OopClosures.hpp" # include "gc/g1/g1_globals.hpp" # include "gc/g1/ptrQueue.hpp" -# include "gc/g1/satbQueue.hpp" +# include "gc/g1/satbMarkQueue.hpp" # include "gc/parallel/gcAdaptivePolicyCounters.hpp" # include "gc/parallel/objectStartArray.hpp" # include "gc/parallel/parMarkBitMap.hpp" diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 5bf88ead017..996180e4713 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -563,7 +563,7 @@ JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub)) // return mirror for superclass Klass* super = k->java_super(); // super2 is the value computed by the compiler's getSuperClass intrinsic: - debug_only(Klass* super2 = ( k->oop_is_array() + debug_only(Klass* super2 = ( k->is_array_klass() ? SystemDictionary::Object_klass() : k->super() ) ); assert(super == super2, @@ -1344,14 +1344,14 @@ static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str, if (name == vmSymbols::object_initializer_name() || name == vmSymbols::class_initializer_name()) { // Never search superclasses for constructors - if (klass->oop_is_instance()) { + if (klass->is_instance_klass()) { m = InstanceKlass::cast(klass())->find_method(name, signature); } else { m = NULL; } } else { m = klass->lookup_method(name, signature); - if (m == NULL && klass->oop_is_instance()) { + if (m == NULL && klass->is_instance_klass()) { m = InstanceKlass::cast(klass())->lookup_method_in_ordered_interfaces(name, signature); } } @@ -2038,7 +2038,7 @@ JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz, k()->initialize(CHECK_NULL); fieldDescriptor fd; - if (!k()->oop_is_instance() || + if (!k()->is_instance_klass() || !InstanceKlass::cast(k())->find_field(fieldname, signame, false, &fd)) { THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } @@ -2292,7 +2292,7 @@ JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz, k()->initialize(CHECK_NULL); fieldDescriptor fd; - if (!k()->oop_is_instance() || + if (!k()->is_instance_klass() || !InstanceKlass::cast(k())->find_field(fieldname, signame, true, &fd)) { THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } @@ -2474,12 +2474,18 @@ JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars( typeArrayOop s_value = java_lang_String::value(s); if (s_value != NULL) { int s_len = java_lang_String::length(s); - int s_offset = java_lang_String::offset(s); + bool is_latin1 = java_lang_String::is_latin1(s); buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination /* JNI Specification states return NULL on OOM */ if (buf != NULL) { if (s_len > 0) { - memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len); + if (!is_latin1) { + memcpy(buf, s_value->char_at_addr(0), sizeof(jchar)*s_len); + } else { + for (int i = 0; i < s_len; i++) { + buf[i] = ((jchar) s_value->byte_at(i)) & 0xff; + } + } } buf[s_len] = 0; //%note jni_5 @@ -3045,7 +3051,7 @@ JNI_ENTRY(jint, jni_UnregisterNatives(JNIEnv *env, jclass clazz)) HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY(env, clazz); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); //%note jni_2 - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { for (int index = 0; index < InstanceKlass::cast(k)->methods()->length(); index++) { Method* m = InstanceKlass::cast(k)->methods()->at(index); if (m->is_native()) { @@ -3118,9 +3124,15 @@ JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, js THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException()); } else { if (len > 0) { - int s_offset = java_lang_String::offset(s); typeArrayOop s_value = java_lang_String::value(s); - memcpy(buf, s_value->char_at_addr(s_offset+start), sizeof(jchar)*len); + bool is_latin1 = java_lang_String::is_latin1(s); + if (!is_latin1) { + memcpy(buf, s_value->char_at_addr(start), sizeof(jchar)*len); + } else { + for (int i = 0; i < len; i++) { + buf[i] = ((jchar) s_value->byte_at(i + start)) & 0xff; + } + } } } JNI_END @@ -3186,18 +3198,23 @@ JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jbool JNIWrapper("GetStringCritical"); HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(env, string, (uintptr_t *) isCopy); GC_locker::lock_critical(thread); - if (isCopy != NULL) { - *isCopy = JNI_FALSE; - } oop s = JNIHandles::resolve_non_null(string); - int s_len = java_lang_String::length(s); typeArrayOop s_value = java_lang_String::value(s); - int s_offset = java_lang_String::offset(s); + bool is_latin1 = java_lang_String::is_latin1(s); + if (isCopy != NULL) { + *isCopy = is_latin1 ? JNI_TRUE : JNI_FALSE; + } const jchar* ret; - if (s_len > 0) { - ret = s_value->char_at_addr(s_offset); + if (!is_latin1) { + ret = s_value->char_at_addr(0); } else { - ret = (jchar*) s_value->base(T_CHAR); + // Inflate latin1 encoded string to UTF16 + int s_len = java_lang_String::length(s); + jchar* buf = NEW_C_HEAP_ARRAY(jchar, s_len, mtInternal); + for (int i = 0; i < s_len; i++) { + buf[i] = ((jchar) s_value->byte_at(i)) & 0xff; + } + ret = &buf[0]; } HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN((uint16_t *) ret); return ret; @@ -3207,7 +3224,14 @@ JNI_END JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars)) JNIWrapper("ReleaseStringCritical"); HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(env, str, (uint16_t *) chars); - // The str and chars arguments are ignored + // The str and chars arguments are ignored for UTF16 strings + oop s = JNIHandles::resolve_non_null(str); + bool is_latin1 = java_lang_String::is_latin1(s); + if (is_latin1) { + // For latin1 string, free jchar array allocated by earlier call to GetStringCritical. + // This assumes that ReleaseStringCritical bookends GetStringCritical. + FREE_C_HEAP_ARRAY(jchar, chars); + } GC_locker::unlock_critical(thread); HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN(); JNI_END @@ -3854,6 +3878,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { unit_test_function_call // Forward declaration +void TestNmethodBucket_test(); void test_semaphore(); void TestOS_test(); void TestReservedSpace_test(); @@ -3868,7 +3893,9 @@ void TestKlass_test(); void TestBitMap_test(); void TestAsUtf8(); void Test_linked_list(); +void TestResourcehash_test(); void TestChunkedList_test(); +void Test_log_length(); #if INCLUDE_ALL_GCS void TestOldFreeSpaceCalculation_test(); void TestG1BiasedArray_test(); @@ -3877,11 +3904,13 @@ void TestCodeCacheRemSet_test(); void FreeRegionList_test(); void test_memset_with_concurrent_readers(); void TestPredictions_test(); +void WorkerDataArray_test(); #endif void execute_internal_vm_tests() { if (ExecuteInternalVMTests) { tty->print_cr("Running internal VM tests"); + run_unit_test(TestNmethodBucket_test()); run_unit_test(test_semaphore()); run_unit_test(TestOS_test()); run_unit_test(TestReservedSpace_test()); @@ -3903,10 +3932,12 @@ void execute_internal_vm_tests() { run_unit_test(TestKlass_test()); run_unit_test(TestBitMap_test()); run_unit_test(TestAsUtf8()); + run_unit_test(TestResourcehash_test()); run_unit_test(ObjectMonitor::sanity_checks()); run_unit_test(Test_linked_list()); run_unit_test(TestChunkedList_test()); run_unit_test(JSONTest::test()); + run_unit_test(Test_log_length()); run_unit_test(DirectivesParser::test()); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs::test()); @@ -3922,6 +3953,7 @@ void execute_internal_vm_tests() { } run_unit_test(test_memset_with_concurrent_readers()); run_unit_test(TestPredictions_test()); + run_unit_test(WorkerDataArray_test()); #endif tty->print_cr("All internal VM tests passed"); } @@ -4063,6 +4095,10 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) { OrderAccess::release_store(&vm_created, 0); } + // Flush stdout and stderr before exit. + fflush(stdout); + fflush(stderr); + return result; } diff --git a/hotspot/src/share/vm/prims/jniCheck.cpp b/hotspot/src/share/vm/prims/jniCheck.cpp index 526eff57099..d8839050411 100644 --- a/hotspot/src/share/vm/prims/jniCheck.cpp +++ b/hotspot/src/share/vm/prims/jniCheck.cpp @@ -514,7 +514,7 @@ void jniCheck::validate_throwable_klass(JavaThread* thr, Klass* klass) { ASSERT_OOPS_ALLOWED; assert(klass != NULL, "klass argument must have a value"); - if (!klass->oop_is_instance() || + if (!klass->is_instance_klass() || !InstanceKlass::cast(klass)->is_subclass_of(SystemDictionary::Throwable_klass())) { ReportJNIFatalError(thr, fatal_class_not_a_throwable_class); } diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index c4e5b4e4a41..d25485c051e 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1022,10 +1022,10 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) KlassHandle klass(thread, java_lang_Class::as_Klass(mirror)); // Figure size of result array int size; - if (klass->oop_is_instance()) { + if (klass->is_instance_klass()) { size = InstanceKlass::cast(klass())->local_interfaces()->length(); } else { - assert(klass->oop_is_objArray() || klass->oop_is_typeArray(), "Illegal mirror klass"); + assert(klass->is_objArray_klass() || klass->is_typeArray_klass(), "Illegal mirror klass"); size = 2; } @@ -1033,7 +1033,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), size, CHECK_NULL); objArrayHandle result (THREAD, r); // Fill in result - if (klass->oop_is_instance()) { + if (klass->is_instance_klass()) { // Regular instance klass, fill in all local interfaces for (int index = 0; index < size; index++) { Klass* k = InstanceKlass::cast(klass())->local_interfaces()->at(index); @@ -1056,7 +1056,7 @@ JVM_QUICK_ENTRY(jboolean, JVM_IsInterface(JNIEnv *env, jclass cls)) } Klass* k = java_lang_Class::as_Klass(mirror); jboolean result = k->is_interface(); - assert(!result || k->oop_is_instance(), + assert(!result || k->is_instance_klass(), "all interfaces are instance types"); // The compiler intrinsic for isInterface tests the // Klass::_access_flags bits in the same way. @@ -1097,7 +1097,7 @@ JVM_ENTRY(void, JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signer // Signers are only set once, ClassLoader.java, and thus shouldn't // be called with an array. Only the bootstrap loader creates arrays. Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { java_lang_Class::set_signers(k->java_mirror(), objArrayOop(JNIHandles::resolve(signers))); } } @@ -1156,7 +1156,7 @@ static bool is_authorized(Handle context, instanceKlassHandle klass, TRAPS) { // Create an AccessControlContext with a protection domain with null codesource // and null permissions - which gives no permissions. oop create_dummy_access_control_context(TRAPS) { - InstanceKlass* pd_klass = InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass()); + InstanceKlass* pd_klass = SystemDictionary::ProtectionDomain_klass(); Handle obj = pd_klass->allocate_instance_handle(CHECK_NULL); // Call constructor ProtectionDomain(null, null); JavaValue result(T_VOID); @@ -1356,7 +1356,7 @@ JVM_END JVM_QUICK_ENTRY(jboolean, JVM_IsArrayClass(JNIEnv *env, jclass cls)) JVMWrapper("JVM_IsArrayClass"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); - return (k != NULL) && k->oop_is_array() ? true : false; + return (k != NULL) && k->is_array_klass() ? true : false; JVM_END @@ -1389,7 +1389,7 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) // of an InstanceKlass if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || - ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_instance()) { + ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) { oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); return (jobjectArray)JNIHandles::make_local(env, result); } @@ -1453,7 +1453,7 @@ JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass)) { // ofClass is a reference to a java_lang_Class object. if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || - ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_instance()) { + ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) { return NULL; } @@ -1471,7 +1471,7 @@ JVM_ENTRY(jstring, JVM_GetSimpleBinaryName(JNIEnv *env, jclass cls)) { oop mirror = JNIHandles::resolve_non_null(cls); if (java_lang_Class::is_primitive(mirror) || - !java_lang_Class::as_Klass(mirror)->oop_is_instance()) { + !java_lang_Class::as_Klass(mirror)->is_instance_klass()) { return NULL; } instanceKlassHandle k(THREAD, InstanceKlass::cast(java_lang_Class::as_Klass(mirror))); @@ -1496,7 +1496,7 @@ JVM_ENTRY(jstring, JVM_GetClassSignature(JNIEnv *env, jclass cls)) // Return null for arrays and primatives if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { Symbol* sym = InstanceKlass::cast(k)->generic_signature(); if (sym == NULL) return NULL; Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); @@ -1514,7 +1514,7 @@ JVM_ENTRY(jbyteArray, JVM_GetClassAnnotations(JNIEnv *env, jclass cls)) // Return null for arrays and primitives if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { typeArrayOop a = Annotations::make_java_array(InstanceKlass::cast(k)->class_annotations(), CHECK_NULL); return (jbyteArray) JNIHandles::make_local(env, a); } @@ -1584,7 +1584,7 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls)) // Return null for arrays and primitives if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { AnnotationArray* type_annotations = InstanceKlass::cast(k)->class_type_annotations(); if (type_annotations != NULL) { typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL); @@ -1693,7 +1693,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, // Exclude primitive types and array types if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || - java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_array()) { + java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) { // Return empty array oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); @@ -1767,7 +1767,7 @@ static jobjectArray get_class_declared_methods_helper( // Exclude primitive types and array types if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) - || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_array()) { + || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) { // Return empty array oop res = oopFactory::new_objArray(klass, 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); @@ -1868,7 +1868,7 @@ JVM_ENTRY(jobject, JVM_GetClassConstantPool(JNIEnv *env, jclass cls)) // Return null for primitives and arrays if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { instanceKlassHandle k_h(THREAD, k); Handle jcp = sun_reflect_ConstantPool::create(CHECK_NULL); sun_reflect_ConstantPool::set_cp(jcp(), k_h->constants()); @@ -2136,8 +2136,8 @@ JVM_ENTRY(jboolean, JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclas if (java_lang_Class::is_primitive(r)) return false; Klass* k = java_lang_Class::as_Klass(r); - assert(k->oop_is_instance(), "must be an instance klass"); - if (! k->oop_is_instance()) return false; + assert(k->is_instance_klass(), "must be an instance klass"); + if (!k->is_instance_klass()) return false; ResourceMark rm(THREAD); const char* name = k->name()->as_C_string(); @@ -2182,12 +2182,12 @@ JVM_QUICK_ENTRY(void, JVM_GetClassCPTypes(JNIEnv *env, jclass cls, unsigned char k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); // types will have length zero if this is not an InstanceKlass // (length is determined by call to JVM_GetClassCPEntriesCount) - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { ConstantPool* cp = InstanceKlass::cast(k)->constants(); for (int index = cp->length() - 1; index >= 0; index--) { constantTag tag = cp->tag_at(index); types[index] = (tag.is_unresolved_klass()) ? JVM_CONSTANT_Class : tag.value(); - } + } } JVM_END @@ -2196,9 +2196,7 @@ JVM_QUICK_ENTRY(jint, JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cls)) JVMWrapper("JVM_GetClassCPEntriesCount"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - if (!k->oop_is_instance()) - return 0; - return InstanceKlass::cast(k)->constants()->length(); + return (!k->is_instance_klass()) ? 0 : InstanceKlass::cast(k)->constants()->length(); JVM_END @@ -2206,9 +2204,7 @@ JVM_QUICK_ENTRY(jint, JVM_GetClassFieldsCount(JNIEnv *env, jclass cls)) JVMWrapper("JVM_GetClassFieldsCount"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - if (!k->oop_is_instance()) - return 0; - return InstanceKlass::cast(k)->java_fields_count(); + return (!k->is_instance_klass()) ? 0 : InstanceKlass::cast(k)->java_fields_count(); JVM_END @@ -2216,9 +2212,7 @@ JVM_QUICK_ENTRY(jint, JVM_GetClassMethodsCount(JNIEnv *env, jclass cls)) JVMWrapper("JVM_GetClassMethodsCount"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - if (!k->oop_is_instance()) - return 0; - return InstanceKlass::cast(k)->methods()->length(); + return (!k->is_instance_klass()) ? 0 : InstanceKlass::cast(k)->methods()->length(); JVM_END @@ -3476,7 +3470,7 @@ jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, KlassHandle klass_handle(THREAD, klass); // Check if we should initialize the class - if (init && klass_handle->oop_is_instance()) { + if (init && klass_handle->is_instance_klass()) { klass_handle->initialize(CHECK_NULL); } return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror()); @@ -3624,7 +3618,7 @@ JVM_ENTRY(jobjectArray, JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)) return NULL; } Klass* k = java_lang_Class::as_Klass(mirror()); - if (!k->oop_is_instance()) { + if (!k->is_instance_klass()) { return NULL; } instanceKlassHandle ik_h(THREAD, k); diff --git a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp index 53b5850712e..c48de41227b 100644 --- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp +++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,7 +125,7 @@ void JvmtiClassFileReconstituter::write_field_infos() { // JVMSpec| u2 attributes_count; // JVMSpec| attribute_info attributes[attributes_count]; // JVMSpec| } -void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) { +void JvmtiClassFileReconstituter::write_code_attribute(const methodHandle& method) { ConstMethod* const_method = method->constMethod(); u2 line_num_cnt = 0; int stackmap_len = 0; @@ -415,7 +415,7 @@ void JvmtiClassFileReconstituter::write_synthetic_attribute() { } // Compute size of LineNumberTable -u2 JvmtiClassFileReconstituter::line_number_table_entries(methodHandle method) { +u2 JvmtiClassFileReconstituter::line_number_table_entries(const methodHandle& method) { // The line number table is compressed so we don't know how big it is until decompressed. // Decompression is really fast so we just do it twice. u2 num_entries = 0; @@ -435,7 +435,7 @@ u2 JvmtiClassFileReconstituter::line_number_table_entries(methodHandle method) { // JVMSpec| u2 line_number; // JVMSpec| } line_number_table[line_number_table_length]; // JVMSpec| } -void JvmtiClassFileReconstituter::write_line_number_table_attribute(methodHandle method, +void JvmtiClassFileReconstituter::write_line_number_table_attribute(const methodHandle& method, u2 num_entries) { write_attribute_name_index("LineNumberTable"); @@ -461,7 +461,7 @@ void JvmtiClassFileReconstituter::write_line_number_table_attribute(methodHandle // JVMSpec| u2 index; // JVMSpec| } local_variable_table[local_variable_table_length]; // JVMSpec| } -void JvmtiClassFileReconstituter::write_local_variable_table_attribute(methodHandle method, u2 num_entries) { +void JvmtiClassFileReconstituter::write_local_variable_table_attribute(const methodHandle& method, u2 num_entries) { write_attribute_name_index("LocalVariableTable"); write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2)); write_u2(num_entries); @@ -491,7 +491,7 @@ void JvmtiClassFileReconstituter::write_local_variable_table_attribute(methodHan // JVMSpec| u2 index; // JVMSpec| } local_variable_type_table[local_variable_type_table_length]; // JVMSpec| } -void JvmtiClassFileReconstituter::write_local_variable_type_table_attribute(methodHandle method, u2 num_entries) { +void JvmtiClassFileReconstituter::write_local_variable_type_table_attribute(const methodHandle& method, u2 num_entries) { write_attribute_name_index("LocalVariableTypeTable"); write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2)); write_u2(num_entries); @@ -519,7 +519,7 @@ void JvmtiClassFileReconstituter::write_local_variable_type_table_attribute(meth // JSR-202| u2 number_of_entries; // JSR-202| stack_map_frame_entries[number_of_entries]; // JSR-202| } -void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle method, +void JvmtiClassFileReconstituter::write_stackmap_table_attribute(const methodHandle& method, int stackmap_len) { write_attribute_name_index("StackMapTable"); @@ -538,7 +538,7 @@ void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle me // JVMSpec| u2 attributes_count; // JVMSpec| attribute_info attributes[attributes_count]; // JVMSpec| } -void JvmtiClassFileReconstituter::write_method_info(methodHandle method) { +void JvmtiClassFileReconstituter::write_method_info(const methodHandle& method) { AccessFlags access_flags = method->access_flags(); ConstMethod* const_method = method->constMethod(); u2 generic_signature_index = const_method->generic_signature_index(); @@ -813,7 +813,7 @@ void JvmtiClassFileReconstituter::write_u8(u8 x) { Bytes::put_Java_u8(writeable_address(8), x); } -void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh, +void JvmtiClassFileReconstituter::copy_bytecodes(const methodHandle& mh, unsigned char* bytecodes) { // use a BytecodeStream to iterate over the bytecodes. JVM/fast bytecodes // and the breakpoint bytecode are converted to their original bytecodes. diff --git a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp index b0c5a4325d9..0dfdec9532c 100644 --- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp +++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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 @@ -110,18 +110,18 @@ class JvmtiClassFileReconstituter : public JvmtiConstantPoolReconstituter { void write_class_file_format(); void write_field_infos(); void write_method_infos(); - void write_method_info(methodHandle method); - void write_code_attribute(methodHandle method); + void write_method_info(const methodHandle& method); + void write_code_attribute(const methodHandle& method); void write_exceptions_attribute(ConstMethod* const_method); void write_synthetic_attribute(); void write_class_attributes(); void write_source_file_attribute(); void write_source_debug_extension_attribute(); - u2 line_number_table_entries(methodHandle method); - void write_line_number_table_attribute(methodHandle method, u2 num_entries); - void write_local_variable_table_attribute(methodHandle method, u2 num_entries); - void write_local_variable_type_table_attribute(methodHandle method, u2 num_entries); - void write_stackmap_table_attribute(methodHandle method, int stackmap_table_len); + u2 line_number_table_entries(const methodHandle& method); + void write_line_number_table_attribute(const methodHandle& method, u2 num_entries); + void write_local_variable_table_attribute(const methodHandle& method, u2 num_entries); + void write_local_variable_type_table_attribute(const methodHandle& method, u2 num_entries); + void write_stackmap_table_attribute(const methodHandle& method, int stackmap_table_len); u2 inner_classes_attribute_length(); void write_inner_classes_attribute(int length); void write_signature_attribute(u2 generic_signaure_index); @@ -150,7 +150,7 @@ class JvmtiClassFileReconstituter : public JvmtiConstantPoolReconstituter { u1* class_file_bytes() { return _buffer; } - static void copy_bytecodes(methodHandle method, unsigned char* bytecodes); + static void copy_bytecodes(const methodHandle& method, unsigned char* bytecodes); }; #endif // SHARE_VM_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP diff --git a/hotspot/src/share/vm/prims/jvmtiEnter.xsl b/hotspot/src/share/vm/prims/jvmtiEnter.xsl index 09cc129fd7c..6842d797b23 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnter.xsl +++ b/hotspot/src/share/vm/prims/jvmtiEnter.xsl @@ -629,8 +629,8 @@ static jvmtiError JNICALL jint trace_flags = JvmtiTrace::trace_flags( ); - const char *func_name; - const char *curr_thread_name; + const char *func_name = NULL; + const char *curr_thread_name = NULL; if (trace_flags) { func_name = JvmtiTrace::function_name( diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index 2738581e042..f048ff17f63 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -966,7 +966,7 @@ JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) { if (name() != NULL) { n = java_lang_String::as_utf8_string(name()); } else { - n = UNICODE::as_utf8(NULL, 0); + n = UNICODE::as_utf8((jchar*) NULL, 0); } info_ptr->name = (char *) jvmtiMalloc(strlen(n)+1); @@ -1187,15 +1187,14 @@ JvmtiEnv::GetThreadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo* info_ptr) Handle group_obj (current_thread, JNIHandles::resolve_external_guard(group)); NULL_CHECK(group_obj(), JVMTI_ERROR_INVALID_THREAD_GROUP); - typeArrayHandle name; + const char* name; Handle parent_group; bool is_daemon; ThreadPriority max_priority; { MutexLocker mu(Threads_lock); - name = typeArrayHandle(current_thread, - java_lang_ThreadGroup::name(group_obj())); + name = java_lang_ThreadGroup::name(group_obj()); parent_group = Handle(current_thread, java_lang_ThreadGroup::parent(group_obj())); is_daemon = java_lang_ThreadGroup::is_daemon(group_obj()); max_priority = java_lang_ThreadGroup::maxPriority(group_obj()); @@ -1205,11 +1204,10 @@ JvmtiEnv::GetThreadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo* info_ptr) info_ptr->max_priority = max_priority; info_ptr->parent = jni_reference(parent_group); - if (name() != NULL) { - const char* n = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); - info_ptr->name = (char *)jvmtiMalloc(strlen(n)+1); + if (name != NULL) { + info_ptr->name = (char*)jvmtiMalloc(strlen(name)+1); NULL_CHECK(info_ptr->name, JVMTI_ERROR_OUT_OF_MEMORY); - strcpy(info_ptr->name, n); + strcpy(info_ptr->name, name); } else { info_ptr->name = NULL; } @@ -2139,7 +2137,7 @@ JvmtiEnv::GetClassSignature(oop k_mirror, char** signature_ptr, char** generic_p } if (generic_ptr != NULL) { *generic_ptr = NULL; - if (!isPrimitive && k->oop_is_instance()) { + if (!isPrimitive && k->is_instance_klass()) { Symbol* soo = InstanceKlass::cast(k)->generic_signature(); if (soo != NULL) { const char *gen_sig = soo->as_C_string(); @@ -2188,7 +2186,7 @@ JvmtiEnv::GetSourceFileName(oop k_mirror, char** source_name_ptr) { Klass* k_klass = java_lang_Class::as_Klass(k_mirror); NULL_CHECK(k_klass, JVMTI_ERROR_INVALID_CLASS); - if (!k_klass->oop_is_instance()) { + if (!k_klass->is_instance_klass()) { return JVMTI_ERROR_ABSENT_INFORMATION; } @@ -2256,7 +2254,7 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth return JVMTI_ERROR_CLASS_NOT_PREPARED; } - if (!k->oop_is_instance()) { + if (!k->is_instance_klass()) { *method_count_ptr = 0; *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID)); return JVMTI_ERROR_NONE; @@ -2340,7 +2338,7 @@ JvmtiEnv::GetClassFields(oop k_mirror, jint* field_count_ptr, jfieldID** fields_ return JVMTI_ERROR_CLASS_NOT_PREPARED; } - if (!k->oop_is_instance()) { + if (!k->is_instance_klass()) { *field_count_ptr = 0; *fields_ptr = (jfieldID*) jvmtiMalloc(0 * sizeof(jfieldID)); return JVMTI_ERROR_NONE; @@ -2394,7 +2392,7 @@ JvmtiEnv::GetImplementedInterfaces(oop k_mirror, jint* interface_count_ptr, jcla if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) return JVMTI_ERROR_CLASS_NOT_PREPARED; - if (!k->oop_is_instance()) { + if (!k->is_instance_klass()) { *interface_count_ptr = 0; *interfaces_ptr = (jclass*) jvmtiMalloc(0 * sizeof(jclass)); return JVMTI_ERROR_NONE; @@ -2528,7 +2526,7 @@ JvmtiEnv::IsArrayClass(oop k_mirror, jboolean* is_array_class_ptr) { bool result = false; if (!java_lang_Class::is_primitive(k_mirror)) { Klass* k = java_lang_Class::as_Klass(k_mirror); - if (k != NULL && k->oop_is_array()) { + if (k != NULL && k->is_array_klass()) { result = true; } } @@ -2576,7 +2574,7 @@ JvmtiEnv::GetSourceDebugExtension(oop k_mirror, char** source_debug_extension_pt } Klass* k = java_lang_Class::as_Klass(k_mirror); NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); - if (!k->oop_is_instance()) { + if (!k->is_instance_klass()) { return JVMTI_ERROR_ABSENT_INFORMATION; } char* sde = InstanceKlass::cast(k)->source_debug_extension(); @@ -3064,7 +3062,7 @@ JvmtiEnv::RawMonitorEnter(JvmtiRawMonitor * rmonitor) { // in thread.cpp. JvmtiPendingMonitors::enter(rmonitor); } else { - int r; + int r = 0; Thread* thread = Thread::current(); if (thread->is_Java_thread()) { @@ -3127,7 +3125,7 @@ JvmtiEnv::RawMonitorExit(JvmtiRawMonitor * rmonitor) { err = JVMTI_ERROR_NOT_MONITOR_OWNER; } } else { - int r; + int r = 0; Thread* thread = Thread::current(); if (thread->is_Java_thread()) { @@ -3161,7 +3159,7 @@ JvmtiEnv::RawMonitorExit(JvmtiRawMonitor * rmonitor) { // rmonitor - pre-checked for validity jvmtiError JvmtiEnv::RawMonitorWait(JvmtiRawMonitor * rmonitor, jlong millis) { - int r; + int r = 0; Thread* thread = Thread::current(); if (thread->is_Java_thread()) { @@ -3220,7 +3218,7 @@ JvmtiEnv::RawMonitorWait(JvmtiRawMonitor * rmonitor, jlong millis) { // rmonitor - pre-checked for validity jvmtiError JvmtiEnv::RawMonitorNotify(JvmtiRawMonitor * rmonitor) { - int r; + int r = 0; Thread* thread = Thread::current(); if (thread->is_Java_thread()) { @@ -3251,7 +3249,7 @@ JvmtiEnv::RawMonitorNotify(JvmtiRawMonitor * rmonitor) { // rmonitor - pre-checked for validity jvmtiError JvmtiEnv::RawMonitorNotifyAll(JvmtiRawMonitor * rmonitor) { - int r; + int r = 0; Thread* thread = Thread::current(); if (thread->is_Java_thread()) { diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index db0437ab119..e8327c2e0ea 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -512,7 +512,7 @@ JvmtiEnvBase::is_thread_fully_suspended(JavaThread* thr, bool wait_for_suspend, // mean much better out of memory handling unsigned char * JvmtiEnvBase::jvmtiMalloc(jlong size) { - unsigned char* mem; + unsigned char* mem = NULL; jvmtiError result = allocate(size, &mem); assert(result == JVMTI_ERROR_NONE, "Allocate failed"); return mem; @@ -1032,7 +1032,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec // implied else: entry_count == 0 } - jint nWant, nWait; + jint nWant = 0, nWait = 0; if (mon != NULL) { // this object has a heavyweight monitor nWant = mon->contentions(); // # of threads contending for monitor diff --git a/hotspot/src/share/vm/prims/jvmtiGen.java b/hotspot/src/share/vm/prims/jvmtiGen.java index f2cdbe9ae72..0b79555b35a 100644 --- a/hotspot/src/share/vm/prims/jvmtiGen.java +++ b/hotspot/src/share/vm/prims/jvmtiGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -22,52 +22,60 @@ * */ +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; - -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.w3c.dom.Document; -import org.w3c.dom.DOMException; -// For write operation import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamResult; -import java.io.*; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.w3c.dom.Document; +import org.w3c.dom.DOMException; public class jvmtiGen { + private static final int EXIT_FAILURE_ERROR = 1; + private static final int EXIT_FAILURE_BADARGUMENTS = 2; + + private static boolean verbose = false; + /** * Write out usage and exit. */ private static void showUsage() { System.err.println("usage:"); System.err.println(" java jvmtiGen " + + "[-verbose] " + "-IN " + "-XSL " + "-OUT " + "[-PARAM ...]"); - System.exit(0); // There is no returning from showUsage() + System.exit(EXIT_FAILURE_BADARGUMENTS); // There is no returning from showUsage() } - // Global value so it can be ref'd by the tree-adapter - static Document document; - - public static void main (String argv []) - { - String inFileName=null; - String xslFileName=null; - String outFileName=null; - java.util.Vector params=new java.util.Vector(); + public static void main (String argv []) { + String inFileName = null; + String xslFileName = null; + String outFileName = null; + final List params = new ArrayList(); for (int ii = 0; ii < argv.length; ii++) { - if (argv[ii].equals("-IN")) { + if (argv[ii].equals("-verbose")) { + verbose = true; + } else if (argv[ii].equals("-IN")) { inFileName = argv[++ii]; } else if (argv[ii].equals("-XSL")) { xslFileName = argv[++ii]; @@ -75,10 +83,10 @@ public class jvmtiGen outFileName = argv[++ii]; } else if (argv[ii].equals("-PARAM")) { if (ii + 2 < argv.length) { - String name = argv[++ii]; - params.addElement(name); - String expression = argv[++ii]; - params.addElement(expression); + final String name = argv[++ii]; + params.add(name); + final String expression = argv[++ii]; + params.add(expression); } else { showUsage(); } @@ -86,109 +94,54 @@ public class jvmtiGen showUsage(); } } - if (inFileName==null || xslFileName==null || outFileName==null){ + if (inFileName == null || xslFileName == null || outFileName == null) { showUsage(); } - /* - * Due to JAXP breakage in some intermediate Tiger builds, the - * com.sun.org.apache..... parser may throw an exception: - * com.sun.org.apache.xml.internal.utils.WrappedRuntimeException: - * org.apache.xalan.serialize.SerializerToText - * - * To work around the problem, this program uses the - * org.apache.xalan.... version if it is available. It is - * available in J2SE 1.4.x and early builds of 1.5 (Tiger). - * It was removed at the same time the thrown exception issue - * above was fixed, so if the class is not found we can proceed - * and use the default parser. - */ - final String parserProperty = - "javax.xml.transform.TransformerFactory"; - final String workaroundParser = - "org.apache.xalan.processor.TransformerFactoryImpl"; - - try { - java.lang.Class cls = java.lang.Class.forName(workaroundParser); - /* - * If we get here, we found the class. Use it. - */ - System.setProperty(parserProperty, workaroundParser); - System.out.println("Info: jvmtiGen using " + parserProperty + - " = " + workaroundParser); - } catch (ClassNotFoundException cnfex) { - /* - * We didn't find workaroundParser. Ignore the - * exception and proceed with default settings. - */ - } - - DocumentBuilderFactory factory = - DocumentBuilderFactory.newInstance(); + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(true); factory.setXIncludeAware(true); - try { - File datafile = new File(inFileName); - File stylesheet = new File(xslFileName); - - DocumentBuilder builder = factory.newDocumentBuilder(); - document = builder.parse(datafile); + final File datafile = new File(inFileName); + final File stylesheet = new File(xslFileName); + try ( + final OutputStream os = new BufferedOutputStream(new FileOutputStream(outFileName)); + ) { + final StreamSource stylesource = new StreamSource(stylesheet); // Use a Transformer for output - TransformerFactory tFactory = - TransformerFactory.newInstance(); - StreamSource stylesource = new StreamSource(stylesheet); - Transformer transformer = tFactory.newTransformer(stylesource); - for (int ii = 0; ii < params.size(); ii += 2){ - transformer.setParameter((String) params.elementAt(ii), - (String) params.elementAt(ii + 1)); + final Transformer transformer = + TransformerFactory.newInstance().newTransformer(stylesource); + for (int ii = 0; ii < params.size(); ii += 2) { + transformer.setParameter(params.get(ii), params.get(ii + 1)); } - DOMSource source = new DOMSource(document); - - PrintStream ps = new PrintStream( new FileOutputStream(outFileName)); - StreamResult result = new StreamResult(ps); + final DocumentBuilder builder = factory.newDocumentBuilder(); + builder.setErrorHandler(new ErrorHandler() { + public void fatalError(SAXParseException exn) throws SAXException { + throw new SAXException(exn); + } + public void error(SAXParseException exn) throws SAXException { + fatalError(exn); + } + public void warning(SAXParseException exn) throws SAXException { + if (verbose) { + System.err.println("jvmtiGen warning: " + exn.getMessage()); + } + } + }); + final Document document = builder.parse(datafile); + final DOMSource source = new DOMSource(document); + final StreamResult result = new StreamResult(os); transformer.transform(source, result); - - } catch (TransformerConfigurationException tce) { - // Error generated by the parser - System.out.println ("\n** Transformer Factory error"); - System.out.println(" " + tce.getMessage() ); - - // Use the contained exception, if any - Throwable x = tce; - if (tce.getException() != null) - x = tce.getException(); - x.printStackTrace(); - - } catch (TransformerException te) { - // Error generated by the parser - System.out.println ("\n** Transformation error"); - System.out.println(" " + te.getMessage() ); - - // Use the contained exception, if any - Throwable x = te; - if (te.getException() != null) - x = te.getException(); - x.printStackTrace(); - - } catch (SAXException sxe) { - // Error generated by this application - // (or a parser-initialization error) - Exception x = sxe; - if (sxe.getException() != null) - x = sxe.getException(); - x.printStackTrace(); - - } catch (ParserConfigurationException pce) { - // Parser with specified options can't be built - pce.printStackTrace(); - - } catch (IOException ioe) { - // I/O error - ioe.printStackTrace(); + } catch (IOException + | ParserConfigurationException + | SAXException + | TransformerException exn) { + System.err.print("jvmtiGen error: " + exn.getMessage()); + exn.printStackTrace(System.err); + System.exit(EXIT_FAILURE_ERROR); } } // main } diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index b55e6e6d9a3..d05813da6a8 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -104,7 +104,7 @@ bool VM_RedefineClasses::doit_prologue() { ClassLoaderData* cld = _scratch_classes[i]->class_loader_data(); // Free the memory for this class at class unloading time. Not before // because CMS might think this is still live. - cld->add_to_deallocate_list((InstanceKlass*)_scratch_classes[i]); + cld->add_to_deallocate_list(InstanceKlass::cast(_scratch_classes[i])); } } // Free os::malloc allocated memory in load_new_class_version. @@ -199,7 +199,7 @@ bool VM_RedefineClasses::is_modifiable_class(oop klass_mirror) { } Klass* the_class_oop = java_lang_Class::as_Klass(klass_mirror); // classes for arrays cannot be redefined - if (the_class_oop == NULL || !the_class_oop->oop_is_instance()) { + if (the_class_oop == NULL || !the_class_oop->is_instance_klass()) { return false; } return true; @@ -216,7 +216,7 @@ bool VM_RedefineClasses::is_modifiable_class(oop klass_mirror) { // referenced CP entries may already exist in *merge_cp_p in which case // there is nothing extra to append and only the current entry is // appended. -void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, +void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { @@ -336,7 +336,7 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i, merge_cp_p, merge_cp_length_p, THREAD); - const char *entry_name; + const char *entry_name = NULL; switch (scratch_cp->tag_at(scratch_i).value()) { case JVM_CONSTANT_Fieldref: entry_name = "Fieldref"; @@ -475,7 +475,7 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, } // end append_entry() -int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp, +int VM_RedefineClasses::find_or_append_indirect_entry(const constantPoolHandle& scratch_cp, int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { int new_ref_i = ref_i; @@ -507,7 +507,7 @@ int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch // Append a bootstrap specifier into the merge_cp operands that is semantically equal // to the scratch_cp operands bootstrap specifier passed by the old_bs_i index. // Recursively append new merge_cp entries referenced by the new bootstrap specifier. -void VM_RedefineClasses::append_operand(constantPoolHandle scratch_cp, int old_bs_i, +void VM_RedefineClasses::append_operand(const constantPoolHandle& scratch_cp, int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { int old_ref_i = scratch_cp->operand_bootstrap_method_ref_index_at(old_bs_i); @@ -551,7 +551,7 @@ void VM_RedefineClasses::append_operand(constantPoolHandle scratch_cp, int old_b } // end append_operand() -int VM_RedefineClasses::find_or_append_operand(constantPoolHandle scratch_cp, +int VM_RedefineClasses::find_or_append_operand(const constantPoolHandle& scratch_cp, int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { int new_bs_i = old_bs_i; // bootstrap specifier index @@ -577,7 +577,7 @@ int VM_RedefineClasses::find_or_append_operand(constantPoolHandle scratch_cp, } // end find_or_append_operand() -void VM_RedefineClasses::finalize_operands_merge(constantPoolHandle merge_cp, TRAPS) { +void VM_RedefineClasses::finalize_operands_merge(const constantPoolHandle& merge_cp, TRAPS) { if (merge_cp->operands() == NULL) { return; } @@ -910,8 +910,8 @@ int VM_RedefineClasses::find_new_operand_index(int old_index) { // Returns true if the current mismatch is due to a resolved/unresolved // class pair. Otherwise, returns false. -bool VM_RedefineClasses::is_unresolved_class_mismatch(constantPoolHandle cp1, - int index1, constantPoolHandle cp2, int index2) { +bool VM_RedefineClasses::is_unresolved_class_mismatch(const constantPoolHandle& cp1, + int index1, const constantPoolHandle& cp2, int index2) { jbyte t1 = cp1->tag_at(index1).value(); if (t1 != JVM_CONSTANT_Class && t1 != JVM_CONSTANT_UnresolvedClass) { @@ -1149,7 +1149,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { // Map old_index to new_index as needed. scratch_cp is only needed // for RC_TRACE() calls. -void VM_RedefineClasses::map_index(constantPoolHandle scratch_cp, +void VM_RedefineClasses::map_index(const constantPoolHandle& scratch_cp, int old_index, int new_index) { if (find_new_index(old_index) != 0) { // old_index is already mapped @@ -1195,8 +1195,8 @@ void VM_RedefineClasses::map_operand_index(int old_index, int new_index) { // scratch_cp to the corresponding entry in *merge_cp_p. Index map // entries are only created for entries in scratch_cp that occupy a // different location in *merged_cp_p. -bool VM_RedefineClasses::merge_constant_pools(constantPoolHandle old_cp, - constantPoolHandle scratch_cp, constantPoolHandle *merge_cp_p, +bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, + const constantPoolHandle& scratch_cp, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { if (merge_cp_p == NULL) { @@ -1892,7 +1892,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_annotation_struct( } u2 type_index = rewrite_cp_ref_in_annotation_data(annotations_typeArray, - byte_i_ref, "mapped old type_index=%d", THREAD); + byte_i_ref, "type_index", THREAD); u2 num_element_value_pairs = Bytes::get_Java_u2((address) annotations_typeArray->adr_at(byte_i_ref)); @@ -1915,7 +1915,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_annotation_struct( u2 element_name_index = rewrite_cp_ref_in_annotation_data( annotations_typeArray, byte_i_ref, - "mapped old element_name_index=%d", THREAD); + "element_name_index", THREAD); RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("element_name_index=%d", element_name_index)); @@ -1939,8 +1939,6 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_annotation_struct( // annotations_typeArray if needed. Returns the original constant // pool reference if a rewrite was not needed or the new constant // pool reference if a rewrite was needed. -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED u2 VM_RedefineClasses::rewrite_cp_ref_in_annotation_data( AnnotationArray* annotations_typeArray, int &byte_i_ref, const char * trace_mesg, TRAPS) { @@ -1950,14 +1948,13 @@ u2 VM_RedefineClasses::rewrite_cp_ref_in_annotation_data( u2 old_cp_index = Bytes::get_Java_u2(cp_index_addr); u2 new_cp_index = find_new_index(old_cp_index); if (new_cp_index != 0) { - RC_TRACE_WITH_THREAD(0x02000000, THREAD, (trace_mesg, old_cp_index)); + RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("mapped old %s=%d", trace_mesg, old_cp_index)); Bytes::put_Java_u2(cp_index_addr, new_cp_index); old_cp_index = new_cp_index; } byte_i_ref += 2; return old_cp_index; } -PRAGMA_DIAG_POP // Rewrite constant pool references in the element_value portion of an @@ -2022,7 +2019,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_element_value( u2 const_value_index = rewrite_cp_ref_in_annotation_data( annotations_typeArray, byte_i_ref, - "mapped old const_value_index=%d", THREAD); + "const_value_index", THREAD); RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("const_value_index=%d", const_value_index)); @@ -2041,11 +2038,11 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_element_value( u2 type_name_index = rewrite_cp_ref_in_annotation_data( annotations_typeArray, byte_i_ref, - "mapped old type_name_index=%d", THREAD); + "type_name_index", THREAD); u2 const_name_index = rewrite_cp_ref_in_annotation_data( annotations_typeArray, byte_i_ref, - "mapped old const_name_index=%d", THREAD); + "const_name_index", THREAD); RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("type_name_index=%d const_name_index=%d", type_name_index, @@ -2065,7 +2062,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_element_value( u2 class_info_index = rewrite_cp_ref_in_annotation_data( annotations_typeArray, byte_i_ref, - "mapped old class_info_index=%d", THREAD); + "class_info_index", THREAD); RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("class_info_index=%d", class_info_index)); @@ -2867,7 +2864,7 @@ bool VM_RedefineClasses::skip_type_annotation_type_path( // } // void VM_RedefineClasses::rewrite_cp_refs_in_stack_map_table( - methodHandle method, TRAPS) { + const methodHandle& method, TRAPS) { if (!method->has_stackmap_table()) { return; @@ -3339,10 +3336,10 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { // If the class being redefined is java.lang.Object, we need to fix all // array class vtables also - if (k->oop_is_array() && _the_class_oop == SystemDictionary::Object_klass()) { + if (k->is_array_klass() && _the_class_oop == SystemDictionary::Object_klass()) { k->vtable()->adjust_method_entries(the_class, &trace_name_printed); - } else if (k->oop_is_instance()) { + } else if (k->is_instance_klass()) { HandleMark hm(_thread); InstanceKlass *ik = InstanceKlass::cast(k); @@ -3379,7 +3376,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { // default_vtable_indices for methods already in the vtable. // If redefining Unsafe, walk all the vtables looking for entries. if (ik->vtable_length() > 0 && (_the_class_oop->is_interface() - || _the_class_oop == SystemDictionary::misc_Unsafe_klass() + || _the_class_oop == SystemDictionary::internal_Unsafe_klass() || ik->is_subtype_of(_the_class_oop))) { // ik->vtable() creates a wrapper object; rm cleans it up ResourceMark rm(_thread); @@ -3396,7 +3393,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { // subclass relationship between an interface and an InstanceKlass. // If redefining Unsafe, walk all the itables looking for entries. if (ik->itable_length() > 0 && (_the_class_oop->is_interface() - || _the_class_oop == SystemDictionary::misc_Unsafe_klass() + || _the_class_oop == SystemDictionary::internal_Unsafe_klass() || ik->is_subclass_of(_the_class_oop))) { // ik->itable() creates a wrapper object; rm cleans it up ResourceMark rm(_thread); @@ -3443,7 +3440,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { // Clean method data for this class void VM_RedefineClasses::MethodDataCleaner::do_klass(Klass* k) { - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { InstanceKlass *ik = InstanceKlass::cast(k); // Clean MethodData of this class's methods so they don't refer to // old methods that are no longer running. @@ -4131,9 +4128,9 @@ void VM_RedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) { for (Klass *subk = ik->subklass(); subk != NULL; subk = subk->next_sibling()) { - if (subk->oop_is_instance()) { + if (subk->is_instance_klass()) { // Only update instanceKlasses - InstanceKlass *subik = (InstanceKlass*)subk; + InstanceKlass *subik = InstanceKlass::cast(subk); // recursively do subclasses of the current subclass increment_class_counter(subik, THREAD); } @@ -4158,7 +4155,7 @@ void VM_RedefineClasses::CheckClass::do_klass(Klass* k) { no_old_methods = false; } - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { HandleMark hm(_thread); InstanceKlass *ik = InstanceKlass::cast(k); diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp index d8dd5cea40e..b4c0cc63694 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp @@ -420,23 +420,23 @@ class VM_RedefineClasses: public VM_Operation { void increment_class_counter(InstanceKlass *ik, TRAPS); // Support for constant pool merging (these routines are in alpha order): - void append_entry(constantPoolHandle scratch_cp, int scratch_i, + void append_entry(const constantPoolHandle& scratch_cp, int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); - void append_operand(constantPoolHandle scratch_cp, int scratch_bootstrap_spec_index, + void append_operand(const constantPoolHandle& scratch_cp, int scratch_bootstrap_spec_index, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); - void finalize_operands_merge(constantPoolHandle merge_cp, TRAPS); - int find_or_append_indirect_entry(constantPoolHandle scratch_cp, int scratch_i, + void finalize_operands_merge(const constantPoolHandle& merge_cp, TRAPS); + int find_or_append_indirect_entry(const constantPoolHandle& scratch_cp, int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); - int find_or_append_operand(constantPoolHandle scratch_cp, int scratch_bootstrap_spec_index, + int find_or_append_operand(const constantPoolHandle& scratch_cp, int scratch_bootstrap_spec_index, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); int find_new_index(int old_index); int find_new_operand_index(int old_bootstrap_spec_index); - bool is_unresolved_class_mismatch(constantPoolHandle cp1, int index1, - constantPoolHandle cp2, int index2); - void map_index(constantPoolHandle scratch_cp, int old_index, int new_index); + bool is_unresolved_class_mismatch(const constantPoolHandle& cp1, int index1, + const constantPoolHandle& cp2, int index2); + void map_index(const constantPoolHandle& scratch_cp, int old_index, int new_index); void map_operand_index(int old_bootstrap_spec_index, int new_bootstrap_spec_index); - bool merge_constant_pools(constantPoolHandle old_cp, - constantPoolHandle scratch_cp, constantPoolHandle *merge_cp_p, + bool merge_constant_pools(const constantPoolHandle& old_cp, + const constantPoolHandle& scratch_cp, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); jvmtiError merge_cp_and_rewrite(instanceKlassHandle the_class, instanceKlassHandle scratch_class, TRAPS); @@ -480,7 +480,7 @@ class VM_RedefineClasses: public VM_Operation { instanceKlassHandle scratch_class, TRAPS); bool rewrite_cp_refs_in_methods_type_annotations( instanceKlassHandle scratch_class, TRAPS); - void rewrite_cp_refs_in_stack_map_table(methodHandle method, TRAPS); + void rewrite_cp_refs_in_stack_map_table(const methodHandle& method, TRAPS); void rewrite_cp_refs_in_verification_type_info( address& stackmap_addr_ref, address stackmap_end, u2 frame_i, u1 frame_size, TRAPS); diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index ecc28a28d32..a468a62e571 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -588,7 +588,7 @@ class CallbackWrapper : public StackObj { _obj_tag = (_entry == NULL) ? 0 : _entry->tag(); // get the class and the class's tag value - assert(InstanceKlass::cast(SystemDictionary::Class_klass())->is_mirror_instance_klass(), "Is not?"); + assert(SystemDictionary::Class_klass()->is_mirror_instance_klass(), "Is not?"); _klass_tag = tag_for(tag_map, _o->klass()->java_mirror()); } @@ -1057,21 +1057,36 @@ static jint invoke_string_value_callback(jvmtiStringPrimitiveValueCallback cb, // get the string value and length // (string value may be offset from the base) int s_len = java_lang_String::length(str); - int s_offset = java_lang_String::offset(str); + bool is_latin1 = java_lang_String::is_latin1(str); jchar* value; if (s_len > 0) { - value = s_value->char_at_addr(s_offset); + if (!is_latin1) { + value = s_value->char_at_addr(0); + } else { + // Inflate latin1 encoded string to UTF16 + jchar* buf = NEW_C_HEAP_ARRAY(jchar, s_len, mtInternal); + for (int i = 0; i < s_len; i++) { + buf[i] = ((jchar) s_value->byte_at(i)) & 0xff; + } + value = &buf[0]; + } } else { + // Don't use char_at_addr(0) if length is 0 value = (jchar*) s_value->base(T_CHAR); } // invoke the callback - return (*cb)(wrapper->klass_tag(), - wrapper->obj_size(), - wrapper->obj_tag_p(), - value, - (jint)s_len, - user_data); + jint res = (*cb)(wrapper->klass_tag(), + wrapper->obj_size(), + wrapper->obj_tag_p(), + value, + (jint)s_len, + user_data); + + if (is_latin1 && s_len > 0) { + FREE_C_HEAP_ARRAY(jchar, value); + } + return res; } // helper function to invoke string primitive value callback @@ -1118,7 +1133,7 @@ static jint invoke_primitive_field_callback_for_static_fields Klass* klass = java_lang_Class::as_Klass(obj); // ignore classes for object and type arrays - if (!klass->oop_is_instance()) { + if (!klass->is_instance_klass()) { return 0; } @@ -2569,7 +2584,7 @@ class SimpleRootsClosure : public OopClosure { // SystemDictionary::always_strong_oops_do reports the application // class loader as a root. We want this root to be reported as // a root kind of "OTHER" rather than "SYSTEM_CLASS". - if (!o->is_instanceMirror()) { + if (!o->is_instance() || !InstanceKlass::cast(o->klass())->is_mirror_instance_klass()) { kind = JVMTI_HEAP_REFERENCE_OTHER; } } @@ -2821,7 +2836,7 @@ inline bool VM_HeapWalkOperation::iterate_over_class(oop java_class) { int i; Klass* klass = java_lang_Class::as_Klass(java_class); - if (klass->oop_is_instance()) { + if (klass->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(klass); // Ignore the class if it hasn't been initialized yet diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 05b5abb83a8..0f58dde7063 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -148,7 +148,7 @@ oop MethodHandles::init_MemberName(Handle mname, Handle target) { oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); - if (!k.is_null() && k->oop_is_instance()) { + if (!k.is_null() && k->is_instance_klass()) { fieldDescriptor fd(InstanceKlass::cast(k()), slot); oop mname2 = init_field_MemberName(mname, fd); if (mname2 != NULL) { @@ -164,7 +164,7 @@ oop MethodHandles::init_MemberName(Handle mname, Handle target) { oop clazz = java_lang_reflect_Method::clazz(target_oop); int slot = java_lang_reflect_Method::slot(target_oop); KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); - if (!k.is_null() && k->oop_is_instance()) { + if (!k.is_null() && k->is_instance_klass()) { Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); if (m == NULL || is_signature_polymorphic(m->intrinsic_id())) return NULL; // do not resolve unless there is a concrete signature @@ -175,7 +175,7 @@ oop MethodHandles::init_MemberName(Handle mname, Handle target) { oop clazz = java_lang_reflect_Constructor::clazz(target_oop); int slot = java_lang_reflect_Constructor::slot(target_oop); KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); - if (!k.is_null() && k->oop_is_instance()) { + if (!k.is_null() && k->is_instance_klass()) { Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); if (m == NULL) return NULL; CallInfo info(m, k()); @@ -637,8 +637,8 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS { Klass* defc_klass = java_lang_Class::as_Klass(defc_oop()); if (defc_klass == NULL) return empty; // a primitive; no resolution possible - if (!defc_klass->oop_is_instance()) { - if (!defc_klass->oop_is_array()) return empty; + if (!defc_klass->is_instance_klass()) { + if (!defc_klass->is_array_klass()) return empty; defc_klass = SystemDictionary::Object_klass(); } defc = instanceKlassHandle(THREAD, defc_klass); @@ -804,7 +804,7 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { case IS_FIELD: { assert(vmtarget->is_klass(), "field vmtarget is Klass*"); - if (!((Klass*) vmtarget)->oop_is_instance()) break; + if (!((Klass*) vmtarget)->is_instance_klass()) break; instanceKlassHandle defc(THREAD, (Klass*) vmtarget); DEBUG_ONLY(vmtarget = NULL); // safety bool is_static = ((flags & JVM_ACC_STATIC) != 0); @@ -841,7 +841,7 @@ int MethodHandles::find_MemberNames(KlassHandle k, Thread* thread = Thread::current(); - if (k.is_null() || !k->oop_is_instance()) return -1; + if (k.is_null() || !k->is_instance_klass()) return -1; int rfill = 0, rlimit = results->length(), rskip = skip; // overflow measurement: @@ -1164,12 +1164,12 @@ JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, if (VerifyMethodHandles && caller_jh != NULL && java_lang_invoke_MemberName::clazz(mname()) != NULL) { Klass* reference_klass = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname())); - if (reference_klass != NULL && reference_klass->oop_is_objArray()) { + if (reference_klass != NULL && reference_klass->is_objArray_klass()) { reference_klass = ObjArrayKlass::cast(reference_klass)->bottom_klass(); } // Reflection::verify_class_access can only handle instance classes. - if (reference_klass != NULL && reference_klass->oop_is_instance()) { + if (reference_klass != NULL && reference_klass->is_instance_klass()) { // Emulate LinkResolver::check_klass_accessability. Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh)); if (!Reflection::verify_class_access(caller, diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp index 41eff71f8f6..fecef0a5055 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.cpp +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp @@ -67,7 +67,7 @@ static void mangle_name_on(outputStream* st, Symbol* name) { } -char* NativeLookup::pure_jni_name(methodHandle method) { +char* NativeLookup::pure_jni_name(const methodHandle& method) { stringStream st; // Prefix st.print("Java_"); @@ -80,7 +80,7 @@ char* NativeLookup::pure_jni_name(methodHandle method) { } -char* NativeLookup::critical_jni_name(methodHandle method) { +char* NativeLookup::critical_jni_name(const methodHandle& method) { stringStream st; // Prefix st.print("JavaCritical_"); @@ -93,7 +93,7 @@ char* NativeLookup::critical_jni_name(methodHandle method) { } -char* NativeLookup::long_jni_name(methodHandle method) { +char* NativeLookup::long_jni_name(const methodHandle& method) { // Signature ignore the wrapping parenteses and the trailing return type stringStream st; Symbol* signature = method->signature(); @@ -121,6 +121,7 @@ extern "C" { #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) static JNINativeMethod lookup_special_native_methods[] = { + { CC"Java_jdk_internal_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterUnsafeMethods) }, { CC"Java_sun_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterUnsafeMethods) }, { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) }, { CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) }, @@ -142,7 +143,7 @@ static address lookup_special_native(char* jni_name) { return NULL; } -address NativeLookup::lookup_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS) { +address NativeLookup::lookup_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS) { address entry; // Compute complete JNI name for style stringStream st; @@ -199,7 +200,7 @@ address NativeLookup::lookup_style(methodHandle method, char* pure_name, const c } -address NativeLookup::lookup_critical_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style) { +address NativeLookup::lookup_critical_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style) { if (!method->has_native_function()) { return NULL; } @@ -229,7 +230,7 @@ address NativeLookup::lookup_critical_style(methodHandle method, char* pure_name // Check all the formats of native implementation name to see if there is one // for the specified method. -address NativeLookup::lookup_entry(methodHandle method, bool& in_base_library, TRAPS) { +address NativeLookup::lookup_entry(const methodHandle& method, bool& in_base_library, TRAPS) { address entry = NULL; in_base_library = false; // Compute pure name @@ -264,7 +265,7 @@ address NativeLookup::lookup_entry(methodHandle method, bool& in_base_library, T // Check all the formats of native implementation name to see if there is one // for the specified method. -address NativeLookup::lookup_critical_entry(methodHandle method) { +address NativeLookup::lookup_critical_entry(const methodHandle& method) { if (!CriticalJNINatives) return NULL; if (method->is_synchronized() || @@ -318,7 +319,7 @@ address NativeLookup::lookup_critical_entry(methodHandle method) { // If any are found, remove them before attemping the look up of the // native implementation again. // See SetNativeMethodPrefix in the JVM TI Spec for more details. -address NativeLookup::lookup_entry_prefixed(methodHandle method, bool& in_base_library, TRAPS) { +address NativeLookup::lookup_entry_prefixed(const methodHandle& method, bool& in_base_library, TRAPS) { #if INCLUDE_JVMTI ResourceMark rm(THREAD); @@ -354,7 +355,7 @@ address NativeLookup::lookup_entry_prefixed(methodHandle method, bool& in_base_l return NULL; } -address NativeLookup::lookup_base(methodHandle method, bool& in_base_library, TRAPS) { +address NativeLookup::lookup_base(const methodHandle& method, bool& in_base_library, TRAPS) { address entry = NULL; ResourceMark rm(THREAD); @@ -372,7 +373,7 @@ address NativeLookup::lookup_base(methodHandle method, bool& in_base_library, TR } -address NativeLookup::lookup(methodHandle method, bool& in_base_library, TRAPS) { +address NativeLookup::lookup(const methodHandle& method, bool& in_base_library, TRAPS) { if (!method->has_native_function()) { address entry = lookup_base(method, in_base_library, CHECK_NULL); method->set_native_function(entry, diff --git a/hotspot/src/share/vm/prims/nativeLookup.hpp b/hotspot/src/share/vm/prims/nativeLookup.hpp index c7ffeb3cda3..d1cfcb9259a 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.hpp +++ b/hotspot/src/share/vm/prims/nativeLookup.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -34,20 +34,20 @@ class NativeLookup : AllStatic { private: // JNI name computation - static char* pure_jni_name(methodHandle method); - static char* long_jni_name(methodHandle method); - static char* critical_jni_name(methodHandle method); + static char* pure_jni_name(const methodHandle& method); + static char* long_jni_name(const methodHandle& method); + static char* critical_jni_name(const methodHandle& method); // Style specific lookup - static address lookup_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS); - static address lookup_critical_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style); - static address lookup_base (methodHandle method, bool& in_base_library, TRAPS); - static address lookup_entry(methodHandle method, bool& in_base_library, TRAPS); - static address lookup_entry_prefixed(methodHandle method, bool& in_base_library, TRAPS); + static address lookup_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS); + static address lookup_critical_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style); + static address lookup_base (const methodHandle& method, bool& in_base_library, TRAPS); + static address lookup_entry(const methodHandle& method, bool& in_base_library, TRAPS); + static address lookup_entry_prefixed(const methodHandle& method, bool& in_base_library, TRAPS); public: // Lookup native function. May throw UnsatisfiedLinkError. - static address lookup(methodHandle method, bool& in_base_library, TRAPS); - static address lookup_critical_entry(methodHandle method); + static address lookup(const methodHandle& method, bool& in_base_library, TRAPS); + static address lookup_critical_entry(const methodHandle& method); // Lookup native functions in base library. static address base_library_lookup(const char* class_name, const char* method_name, const char* signature); diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 2d449258660..d2d1f0bb866 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -45,7 +45,7 @@ #endif // INCLUDE_ALL_GCS /* - * Implementation of class sun.misc.Unsafe + * Implementation of class Unsafe */ @@ -766,12 +766,12 @@ static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) { } oop mirror = JNIHandles::resolve_non_null(acls); Klass* k = java_lang_Class::as_Klass(mirror); - if (k == NULL || !k->oop_is_array()) { + if (k == NULL || !k->is_array_klass()) { THROW(vmSymbols::java_lang_InvalidClassException()); - } else if (k->oop_is_objArray()) { + } else if (k->is_objArray_klass()) { base = arrayOopDesc::base_offset_in_bytes(T_OBJECT); scale = heapOopSize; - } else if (k->oop_is_typeArray()) { + } else if (k->is_typeArray_klass()) { TypeArrayKlass* tak = TypeArrayKlass::cast(k); base = tak->array_header_in_bytes(); assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok"); @@ -783,7 +783,7 @@ static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) { UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset(JNIEnv *env, jobject unsafe, jclass acls)) UnsafeWrapper("Unsafe_ArrayBaseOffset"); - int base, scale; + int base = 0, scale = 0; getBaseAndScale(base, scale, acls, CHECK_0); return field_offset_from_byte_offset(base); UNSAFE_END @@ -791,7 +791,7 @@ UNSAFE_END UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass acls)) UnsafeWrapper("Unsafe_ArrayIndexScale"); - int base, scale; + int base = 0, scale = 0; getBaseAndScale(base, scale, acls, CHECK_0); // This VM packs both fields and array elements down to the byte. // But watch out: If this changes, so that array references for diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index dfd715a5f12..a386a3f5313 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -322,8 +322,8 @@ WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o)) WB_END WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o)) - G1CollectedHeap* g1 = G1CollectedHeap::heap(); - return g1->concurrent_mark()->cmThread()->during_cycle(); + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + return g1h->concurrent_mark()->cmThread()->during_cycle(); WB_END WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o)) @@ -1028,17 +1028,19 @@ struct CodeBlobStub { CodeBlobStub(const CodeBlob* blob) : name(os::strdup(blob->name())), size(blob->size()), - blob_type(WhiteBox::get_blob_type(blob)) { } + blob_type(WhiteBox::get_blob_type(blob)), + address((jlong) blob) { } ~CodeBlobStub() { os::free((void*) name); } const char* const name; - const int size; - const int blob_type; + const jint size; + const jint blob_type; + const jlong address; }; static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) { jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string()); CHECK_JNI_EXCEPTION_(env, NULL); - jobjectArray result = env->NewObjectArray(3, clazz, NULL); + jobjectArray result = env->NewObjectArray(4, clazz, NULL); jstring name = env->NewStringUTF(cb->name); CHECK_JNI_EXCEPTION_(env, NULL); @@ -1052,6 +1054,10 @@ static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBl CHECK_JNI_EXCEPTION_(env, NULL); env->SetObjectArrayElement(result, 2, obj); + obj = longBox(thread, env, cb->address); + CHECK_JNI_EXCEPTION_(env, NULL); + env->SetObjectArrayElement(result, 3, obj); + return result; } @@ -1092,9 +1098,9 @@ WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jbo CHECK_JNI_EXCEPTION_(env, NULL); env->SetObjectArrayElement(result, 3, id); - jobject address = longBox(thread, env, (jlong) code); + jobject entry_point = longBox(thread, env, (jlong) code->entry_point()); CHECK_JNI_EXCEPTION_(env, NULL); - env->SetObjectArrayElement(result, 4, address); + env->SetObjectArrayElement(result, 4, entry_point); return result; WB_END @@ -1275,9 +1281,9 @@ WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb)) VMThread::execute(&force_safepoint_op); WB_END -WB_ENTRY(long, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass)) +WB_ENTRY(jlong, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass)) instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); - return (long) ikh->constants(); + return (jlong) ikh->constants(); WB_END template diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp index eb58e37c482..cd73fa78559 100644 --- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp @@ -467,14 +467,14 @@ CompLevel AdvancedThresholdPolicy::loop_event(Method* method, CompLevel cur_leve } // Update the rate and submit compile -void AdvancedThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread) { +void AdvancedThresholdPolicy::submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) { int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count(); update_rate(os::javaTimeMillis(), mh()); CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", thread); } // Handle the invocation event. -void AdvancedThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh, +void AdvancedThresholdPolicy::method_invocation_event(const methodHandle& mh, const methodHandle& imh, CompLevel level, nmethod* nm, JavaThread* thread) { if (should_create_mdo(mh(), level)) { create_mdo(mh, thread); @@ -489,7 +489,7 @@ void AdvancedThresholdPolicy::method_invocation_event(methodHandle mh, methodHan // Handle the back branch event. Notice that we can compile the method // with a regular entry from here. -void AdvancedThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh, +void AdvancedThresholdPolicy::method_back_branch_event(const methodHandle& mh, const methodHandle& imh, int bci, CompLevel level, nmethod* nm, JavaThread* thread) { if (should_create_mdo(mh(), level)) { create_mdo(mh, thread); diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp index 5ec406388f3..2ae2ce9e151 100644 --- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp +++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, 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 @@ -213,11 +213,11 @@ protected: jlong start_time() const { return _start_time; } // Submit a given method for compilation (and update the rate). - virtual void submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread); + virtual void submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread); // event() from SimpleThresholdPolicy would call these. - virtual void method_invocation_event(methodHandle method, methodHandle inlinee, + virtual void method_invocation_event(const methodHandle& method, const methodHandle& inlinee, CompLevel level, nmethod* nm, JavaThread* thread); - virtual void method_back_branch_event(methodHandle method, methodHandle inlinee, + virtual void method_back_branch_event(const methodHandle& method, const methodHandle& inlinee, int bci, CompLevel level, nmethod* nm, JavaThread* thread); public: AdvancedThresholdPolicy() : _start_time(0) { } diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index a35a00bb2dd..22b19071b56 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -364,6 +364,7 @@ static SpecialFlag const special_jvm_flags[] = { { "LazyBootClassLoader", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "StarvationMonitorInterval", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "PreInflateSpin", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "JNIDetachReleasesMonitors", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS { "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() }, @@ -817,9 +818,15 @@ static bool set_numeric_flag(const char* name, char* value, Flag::Flags origin) int int_v; intx intx_v; bool is_neg = false; + Flag* result = Flag::find_flag(name, strlen(name)); + + if (result == NULL) { + return false; + } + // Check the sign first since atomull() parses only unsigned values. if (*value == '-') { - if ((CommandLineFlags::intxAt(name, &intx_v) != Flag::SUCCESS) && (CommandLineFlags::intAt(name, &int_v) != Flag::SUCCESS)) { + if (!result->is_intx() && !result->is_int()) { return false; } value++; @@ -828,37 +835,33 @@ static bool set_numeric_flag(const char* name, char* value, Flag::Flags origin) if (!atomull(value, &v)) { return false; } - int_v = (int) v; - if (is_neg) { - int_v = -int_v; + if (result->is_int()) { + int_v = (int) v; + if (is_neg) { + int_v = -int_v; + } + return CommandLineFlags::intAtPut(result, &int_v, origin) == Flag::SUCCESS; + } else if (result->is_uint()) { + uint uint_v = (uint) v; + return CommandLineFlags::uintAtPut(result, &uint_v, origin) == Flag::SUCCESS; + } else if (result->is_intx()) { + intx_v = (intx) v; + if (is_neg) { + intx_v = -intx_v; + } + return CommandLineFlags::intxAtPut(result, &intx_v, origin) == Flag::SUCCESS; + } else if (result->is_uintx()) { + uintx uintx_v = (uintx) v; + return CommandLineFlags::uintxAtPut(result, &uintx_v, origin) == Flag::SUCCESS; + } else if (result->is_uint64_t()) { + uint64_t uint64_t_v = (uint64_t) v; + return CommandLineFlags::uint64_tAtPut(result, &uint64_t_v, origin) == Flag::SUCCESS; + } else if (result->is_size_t()) { + size_t size_t_v = (size_t) v; + return CommandLineFlags::size_tAtPut(result, &size_t_v, origin) == Flag::SUCCESS; + } else { + return false; } - if (CommandLineFlags::intAtPut(name, &int_v, origin) == Flag::SUCCESS) { - return true; - } - uint uint_v = (uint) v; - if (!is_neg && CommandLineFlags::uintAtPut(name, &uint_v, origin) == Flag::SUCCESS) { - return true; - } - intx_v = (intx) v; - if (is_neg) { - intx_v = -intx_v; - } - if (CommandLineFlags::intxAtPut(name, &intx_v, origin) == Flag::SUCCESS) { - return true; - } - uintx uintx_v = (uintx) v; - if (!is_neg && (CommandLineFlags::uintxAtPut(name, &uintx_v, origin) == Flag::SUCCESS)) { - return true; - } - uint64_t uint64_t_v = (uint64_t) v; - if (!is_neg && (CommandLineFlags::uint64_tAtPut(name, &uint64_t_v, origin) == Flag::SUCCESS)) { - return true; - } - size_t size_t_v = (size_t) v; - if (!is_neg && (CommandLineFlags::size_tAtPut(name, &size_t_v, origin) == Flag::SUCCESS)) { - return true; - } - return false; } static bool set_string_flag(const char* name, const char* value, Flag::Flags origin) { @@ -1120,7 +1123,7 @@ bool Arguments::process_argument(const char* arg, Flag::Flags origin) { JDK_Version since = JDK_Version(); - if (parse_argument(arg, origin) || ignore_unrecognized) { + if (parse_argument(arg, origin)) { return true; } @@ -1156,7 +1159,7 @@ bool Arguments::process_argument(const char* arg, Flag* found_flag = Flag::find_flag((const char*)argname, arg_len, true, true); if (found_flag != NULL) { char locked_message_buf[BUFLEN]; - found_flag->get_locked_message(locked_message_buf, BUFLEN); + Flag::MsgType msg_type = found_flag->get_locked_message(locked_message_buf, BUFLEN); if (strlen(locked_message_buf) == 0) { if (found_flag->is_bool() && !has_plus_minus) { jio_fprintf(defaultStream::error_stream(), @@ -1169,9 +1172,19 @@ bool Arguments::process_argument(const char* arg, "Improperly specified VM option '%s'\n", argname); } } else { +#ifdef PRODUCT + bool mismatched = ((msg_type == Flag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD) || + (msg_type == Flag::DEVELOPER_FLAG_BUT_PRODUCT_BUILD)); + if (ignore_unrecognized && mismatched) { + return true; + } +#endif jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf); } } else { + if (ignore_unrecognized) { + return true; + } jio_fprintf(defaultStream::error_stream(), "Unrecognized VM option '%s'\n", argname); Flag* fuzzy_matched = Flag::fuzzy_match((const char*)argname, arg_len, true); @@ -2469,16 +2482,6 @@ bool Arguments::check_vm_args_consistency() { } } - // Note: only executed in non-PRODUCT mode - if (!UseAsyncConcMarkSweepGC && - (ExplicitGCInvokesConcurrent || - ExplicitGCInvokesConcurrentAndUnloadsClasses)) { - jio_fprintf(defaultStream::error_stream(), - "error: +ExplicitGCInvokesConcurrent[AndUnloadsClasses] conflicts" - " with -UseAsyncConcMarkSweepGC"); - status = false; - } - if (PrintNMTStatistics) { #if INCLUDE_NMT if (MemTracker::tracking_level() == NMT_off) { @@ -3481,33 +3484,8 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req sprintf(path, "%s%slib%sendorsed", Arguments::get_java_home(), fileSep, fileSep); #if INCLUDE_JVMCI - jint res = JVMCIRuntime::save_options(_system_properties); - if (res != JNI_OK) { - return res; - } - if (EnableJVMCI) { - // Append lib/jvmci/*.jar to boot class path - char jvmciDir[JVM_MAXPATHLEN]; - const char* fileSep = os::file_separator(); - jio_snprintf(jvmciDir, sizeof(jvmciDir), "%s%slib%sjvmci", Arguments::get_java_home(), fileSep, fileSep); - DIR* dir = os::opendir(jvmciDir); - if (dir != NULL) { - struct dirent *entry; - char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(jvmciDir), mtInternal); - while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { - const char* name = entry->d_name; - const char* ext = name + strlen(name) - 4; - if (ext > name && strcmp(ext, ".jar") == 0) { - char fileName[JVM_MAXPATHLEN]; - jio_snprintf(fileName, sizeof(fileName), "%s%s%s", jvmciDir, fileSep, name); - scp_p->add_suffix(fileName); - scp_assembly_required = true; - } - } - FREE_C_HEAP_ARRAY(char, dbuf); - os::closedir(dir); - } + JVMCIRuntime::save_options(_system_properties); } #endif // INCLUDE_JVMCI @@ -3858,6 +3836,7 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_ JavaVMOption option; option.optionString = opt_hd; + option.extraInfo = NULL; options->append(option); // Fill in option diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp index 7b5485339ae..575531754b2 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp @@ -34,10 +34,10 @@ #include "utilities/defaultStream.hpp" Flag::Error AliasLevelConstraintFunc(intx value, bool verbose) { - if ((value <= 1) && (Arguments::mode() == Arguments::_comp)) { + if ((value <= 1) && (Arguments::mode() == Arguments::_comp || Arguments::mode() == Arguments::_mixed)) { CommandLineError::print(verbose, "AliasLevel (" INTX_FORMAT ") is not " - "compatible with -Xcomp \n", + "compatible with -Xcomp or -Xmixed\n", value); return Flag::VIOLATES_CONSTRAINT; } else { @@ -118,10 +118,10 @@ Flag::Error AllocatePrefetchInstrConstraintFunc(intx value, bool verbose) { } Flag::Error AllocatePrefetchStepSizeConstraintFunc(intx value, bool verbose) { - if (value < 0 || value > max_jint) { + if (value < 1 || value > max_jint) { CommandLineError::print(verbose, "AllocatePrefetchStepSize (" INTX_FORMAT ") " - "must be between 0 and %d\n", + "must be between 1 and %d\n", AllocatePrefetchStepSize, max_jint); return Flag::VIOLATES_CONSTRAINT; @@ -206,7 +206,7 @@ Flag::Error CodeCacheSegmentSizeConstraintFunc(uintx value, bool verbose) { if (CodeCacheSegmentSize < (uintx)CodeEntryAlignment) { CommandLineError::print(verbose, "CodeCacheSegmentSize (" UINTX_FORMAT ") must be " - "larger than or equal to CodeEntryAlignment (" INTX_FORMAT ")" + "larger than or equal to CodeEntryAlignment (" INTX_FORMAT ") " "to align entry points\n", CodeCacheSegmentSize, CodeEntryAlignment); return Flag::VIOLATES_CONSTRAINT; @@ -224,7 +224,7 @@ Flag::Error CodeCacheSegmentSizeConstraintFunc(uintx value, bool verbose) { if (CodeCacheSegmentSize < (uintx)OptoLoopAlignment) { CommandLineError::print(verbose, "CodeCacheSegmentSize (" UINTX_FORMAT ") must be " - "larger than or equal to OptoLoopAlignment (" INTX_FORMAT ")" + "larger than or equal to OptoLoopAlignment (" INTX_FORMAT ") " "to align inner loops\n", CodeCacheSegmentSize, OptoLoopAlignment); return Flag::VIOLATES_CONSTRAINT; @@ -235,15 +235,17 @@ Flag::Error CodeCacheSegmentSizeConstraintFunc(uintx value, bool verbose) { } Flag::Error CompilerThreadPriorityConstraintFunc(intx value, bool verbose) { - if (value < min_jint || value > max_jint) { +#ifdef SOLARIS + if ((value < MinimumPriority || value > MaximumPriority) && + (value != -1) && (value != -FXCriticalPriority)) { CommandLineError::print(verbose, - "CompileThreadPriority (" INTX_FORMAT ") " - "must be between %d and %d. " - "Please also make sure to specify values that are " - "meaningful to your operating system\n", - value, min_jint, max_jint); + "CompileThreadPriority (" INTX_FORMAT ") must be " + "between %d and %d inclusively or -1 (means no change) " + "or %d (special value for critical thread class/priority)\n", + value, MinimumPriority, MaximumPriority, -FXCriticalPriority); return Flag::VIOLATES_CONSTRAINT; } +#endif return Flag::SUCCESS; } @@ -277,14 +279,6 @@ Flag::Error CodeEntryAlignmentConstraintFunc(intx value, bool verbose) { } Flag::Error OptoLoopAlignmentConstraintFunc(intx value, bool verbose) { - if (value < 0 || value > 16) { - CommandLineError::print(verbose, - "OptoLoopAlignment (" INTX_FORMAT ") " - "must be between 0 and 16\n", - value); - return Flag::VIOLATES_CONSTRAINT; - } - if (!is_power_of_2(value)) { CommandLineError::print(verbose, "OptoLoopAlignment (" INTX_FORMAT ") " @@ -308,7 +302,8 @@ Flag::Error OptoLoopAlignmentConstraintFunc(intx value, bool verbose) { Flag::Error ArraycopyDstPrefetchDistanceConstraintFunc(uintx value, bool verbose) { if (value != 0) { CommandLineError::print(verbose, - "ArraycopyDstPrefetchDistance (" INTX_FORMAT ") must be 0\n"); + "ArraycopyDstPrefetchDistance (" UINTX_FORMAT ") must be 0\n", + value); return Flag::VIOLATES_CONSTRAINT; } @@ -318,7 +313,8 @@ Flag::Error ArraycopyDstPrefetchDistanceConstraintFunc(uintx value, bool verbose Flag::Error ArraycopySrcPrefetchDistanceConstraintFunc(uintx value, bool verbose) { if (value != 0) { CommandLineError::print(verbose, - "ArraycopySrcPrefetchDistance (" INTX_FORMAT ") must be 0\n"); + "ArraycopySrcPrefetchDistance (" UINTX_FORMAT ") must be 0\n", + value); return Flag::VIOLATES_CONSTRAINT; } diff --git a/hotspot/src/share/vm/runtime/compilationPolicy.cpp b/hotspot/src/share/vm/runtime/compilationPolicy.cpp index 09d07a01d64..d6c45d1247f 100644 --- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp +++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, 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 @@ -218,7 +218,7 @@ int NonTieredCompPolicy::compiler_count(CompLevel comp_level) { return 0; } -void NonTieredCompPolicy::reset_counter_for_invocation_event(methodHandle m) { +void NonTieredCompPolicy::reset_counter_for_invocation_event(const methodHandle& m) { // Make sure invocation and backedge counter doesn't overflow again right away // as would be the case for native methods. @@ -232,7 +232,7 @@ void NonTieredCompPolicy::reset_counter_for_invocation_event(methodHandle m) { assert(!m->was_never_executed(), "don't reset to 0 -- could be mistaken for never-executed"); } -void NonTieredCompPolicy::reset_counter_for_back_branch_event(methodHandle m) { +void NonTieredCompPolicy::reset_counter_for_back_branch_event(const methodHandle& m) { // Delay next back-branch event but pump up invocation counter to trigger // whole method compilation. MethodCounters* mcs = m->method_counters(); @@ -283,7 +283,7 @@ void CounterDecay::decay() { CounterHalfLifeTime); for (int i = 0; i < classes_per_tick; i++) { Klass* k = SystemDictionary::try_get_next_class(); - if (k != NULL && k->oop_is_instance()) { + if (k != NULL && k->is_instance_klass()) { InstanceKlass::cast(k)->methods_do(do_method); } } @@ -357,7 +357,7 @@ bool NonTieredCompPolicy::is_mature(Method* method) { return (current >= initial + target); } -nmethod* NonTieredCompPolicy::event(methodHandle method, methodHandle inlinee, int branch_bci, +nmethod* NonTieredCompPolicy::event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) { assert(comp_level == CompLevel_none, "This should be only called from the interpreter"); NOT_PRODUCT(trace_frequency_counter_overflow(method, branch_bci, bci)); @@ -416,22 +416,18 @@ nmethod* NonTieredCompPolicy::event(methodHandle method, methodHandle inlinee, i } #ifndef PRODUCT -PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL -void NonTieredCompPolicy::trace_frequency_counter_overflow(methodHandle m, int branch_bci, int bci) { +void NonTieredCompPolicy::trace_frequency_counter_overflow(const methodHandle& m, int branch_bci, int bci) { if (TraceInvocationCounterOverflow) { MethodCounters* mcs = m->method_counters(); assert(mcs != NULL, "MethodCounters cannot be NULL for profiling"); InvocationCounter* ic = mcs->invocation_counter(); InvocationCounter* bc = mcs->backedge_counter(); ResourceMark rm; - const char* msg = - bci == InvocationEntryBci - ? "comp-policy cntr ovfl @ %d in entry of " - : "comp-policy cntr ovfl @ %d in loop of "; -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL - tty->print(msg, bci); -PRAGMA_DIAG_POP + if (bci == InvocationEntryBci) { + tty->print("comp-policy cntr ovfl @ %d in entry of ", bci); + } else { + tty->print("comp-policy cntr ovfl @ %d in loop of ", bci); + } m->print_value(); tty->cr(); ic->print(); @@ -448,7 +444,7 @@ PRAGMA_DIAG_POP } } -void NonTieredCompPolicy::trace_osr_request(methodHandle method, nmethod* osr, int bci) { +void NonTieredCompPolicy::trace_osr_request(const methodHandle& method, nmethod* osr, int bci) { if (TraceOnStackReplacement) { ResourceMark rm; tty->print(osr != NULL ? "Reused OSR entry for " : "Requesting OSR entry for "); @@ -460,7 +456,7 @@ void NonTieredCompPolicy::trace_osr_request(methodHandle method, nmethod* osr, i // SimpleCompPolicy - compile current method -void SimpleCompPolicy::method_invocation_event(methodHandle m, JavaThread* thread) { +void SimpleCompPolicy::method_invocation_event(const methodHandle& m, JavaThread* thread) { const int comp_level = CompLevel_highest_tier; const int hot_count = m->invocation_count(); reset_counter_for_invocation_event(m); @@ -474,7 +470,7 @@ void SimpleCompPolicy::method_invocation_event(methodHandle m, JavaThread* threa } } -void SimpleCompPolicy::method_back_branch_event(methodHandle m, int bci, JavaThread* thread) { +void SimpleCompPolicy::method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) { const int comp_level = CompLevel_highest_tier; const int hot_count = m->backedge_count(); const char* comment = "backedge_count"; @@ -491,7 +487,7 @@ const char* StackWalkCompPolicy::_msg = NULL; // Consider m for compilation -void StackWalkCompPolicy::method_invocation_event(methodHandle m, JavaThread* thread) { +void StackWalkCompPolicy::method_invocation_event(const methodHandle& m, JavaThread* thread) { const int comp_level = CompLevel_highest_tier; const int hot_count = m->invocation_count(); reset_counter_for_invocation_event(m); @@ -530,7 +526,7 @@ void StackWalkCompPolicy::method_invocation_event(methodHandle m, JavaThread* th } } -void StackWalkCompPolicy::method_back_branch_event(methodHandle m, int bci, JavaThread* thread) { +void StackWalkCompPolicy::method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) { const int comp_level = CompLevel_highest_tier; const int hot_count = m->backedge_count(); const char* comment = "backedge_count"; @@ -663,7 +659,7 @@ RFrame* StackWalkCompPolicy::senderOf(RFrame* rf, GrowableArray* stack) } -const char* StackWalkCompPolicy::shouldInline(methodHandle m, float freq, int cnt) { +const char* StackWalkCompPolicy::shouldInline(const methodHandle& m, float freq, int cnt) { // Allows targeted inlining // positive filter: should send be inlined? returns NULL (--> yes) // or rejection msg @@ -690,7 +686,7 @@ const char* StackWalkCompPolicy::shouldInline(methodHandle m, float freq, int cn } -const char* StackWalkCompPolicy::shouldNotInline(methodHandle m) { +const char* StackWalkCompPolicy::shouldNotInline(const methodHandle& m) { // negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg if (m->is_abstract()) return (_msg = "abstract method"); // note: we allow ik->is_abstract() diff --git a/hotspot/src/share/vm/runtime/compilationPolicy.hpp b/hotspot/src/share/vm/runtime/compilationPolicy.hpp index 62df7ece209..054671a846d 100644 --- a/hotspot/src/share/vm/runtime/compilationPolicy.hpp +++ b/hotspot/src/share/vm/runtime/compilationPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, 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 @@ -66,7 +66,7 @@ public: virtual int compiler_count(CompLevel comp_level) = 0; // main notification entry, return a pointer to an nmethod if the OSR is required, // returns NULL otherwise. - virtual nmethod* event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) = 0; + virtual nmethod* event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) = 0; // safepoint() is called at the end of the safepoint virtual void do_safepoint_work() = 0; // reprofile request @@ -91,11 +91,11 @@ public: class NonTieredCompPolicy : public CompilationPolicy { int _compiler_count; protected: - static void trace_frequency_counter_overflow(methodHandle m, int branch_bci, int bci); - static void trace_osr_request(methodHandle method, nmethod* osr, int bci); + static void trace_frequency_counter_overflow(const methodHandle& m, int branch_bci, int bci); + static void trace_osr_request(const methodHandle& method, nmethod* osr, int bci); static void trace_osr_completion(nmethod* osr_nm); - void reset_counter_for_invocation_event(methodHandle method); - void reset_counter_for_back_branch_event(methodHandle method); + void reset_counter_for_invocation_event(const methodHandle& method); + void reset_counter_for_back_branch_event(const methodHandle& method); public: NonTieredCompPolicy() : _compiler_count(0) { } virtual CompLevel initial_compile_level() { return CompLevel_highest_tier; } @@ -107,15 +107,15 @@ public: virtual bool is_mature(Method* method); virtual void initialize(); virtual CompileTask* select_task(CompileQueue* compile_queue); - virtual nmethod* event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread); - virtual void method_invocation_event(methodHandle m, JavaThread* thread) = 0; - virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread) = 0; + virtual nmethod* event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread); + virtual void method_invocation_event(const methodHandle& m, JavaThread* thread) = 0; + virtual void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) = 0; }; class SimpleCompPolicy : public NonTieredCompPolicy { public: - virtual void method_invocation_event(methodHandle m, JavaThread* thread); - virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread); + virtual void method_invocation_event(const methodHandle& m, JavaThread* thread); + virtual void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread); }; // StackWalkCompPolicy - existing C2 policy @@ -123,8 +123,8 @@ class SimpleCompPolicy : public NonTieredCompPolicy { #ifdef COMPILER2 class StackWalkCompPolicy : public NonTieredCompPolicy { public: - virtual void method_invocation_event(methodHandle m, JavaThread* thread); - virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread); + virtual void method_invocation_event(const methodHandle& m, JavaThread* thread); + virtual void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread); private: RFrame* findTopInlinableFrame(GrowableArray* stack); @@ -134,9 +134,9 @@ class StackWalkCompPolicy : public NonTieredCompPolicy { // they are used for performance debugging only (print better messages) static const char* _msg; // reason for not inlining - static const char* shouldInline (methodHandle callee, float frequency, int cnt); + static const char* shouldInline (const methodHandle& callee, float frequency, int cnt); // positive filter: should send be inlined? returns NULL (--> yes) or rejection msg - static const char* shouldNotInline(methodHandle callee); + static const char* shouldNotInline(const methodHandle& callee); // negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg }; diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index a79acbcede7..ab733a9974f 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -758,15 +758,15 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArra KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())); oop obj = NULL; - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k()); obj = ik->allocate_instance(THREAD); - } else if (k->oop_is_typeArray()) { + } else if (k->is_typeArray_klass()) { TypeArrayKlass* ak = TypeArrayKlass::cast(k()); assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length"); int len = sv->field_size() / type2size[ak->element_type()]; obj = ak->allocate(len, THREAD); - } else if (k->oop_is_objArray()) { + } else if (k->is_objArray_klass()) { ObjArrayKlass* ak = ObjArrayKlass::cast(k()); obj = ak->allocate(sv->field_size(), THREAD); } @@ -1010,13 +1010,13 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr continue; } - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k()); reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), skip_internal); - } else if (k->oop_is_typeArray()) { + } else if (k->is_typeArray_klass()) { TypeArrayKlass* ak = TypeArrayKlass::cast(k()); reassign_type_array_elements(fr, reg_map, sv, (typeArrayOop) obj(), ak->element_type()); - } else if (k->oop_is_objArray()) { + } else if (k->is_objArray_klass()) { reassign_object_array_elements(fr, reg_map, sv, (objArrayOop) obj()); } } @@ -1345,7 +1345,7 @@ Deoptimization::get_method_data(JavaThread* thread, methodHandle m, } #if defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI -void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS) { +void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool, int index, TRAPS) { // in case of an unresolved klass entry, load the class. if (constant_pool->tag_at(index).is_unresolved_klass()) { Klass* tk = constant_pool->klass_at_ignore_error(index, CHECK); @@ -1376,7 +1376,7 @@ void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int i } -void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index) { +void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool, int index) { EXCEPTION_MARK; load_class_by_index(constant_pool, index, THREAD); if (HAS_PENDING_EXCEPTION) { @@ -1461,14 +1461,14 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra oop speculation_log = nm->speculation_log(); if (speculation_log != NULL) { if (TraceDeoptimization || TraceUncollectedSpeculations) { - if (SpeculationLog::lastFailed(speculation_log) != NULL) { + if (HotSpotSpeculationLog::lastFailed(speculation_log) != NULL) { tty->print_cr("A speculation that was not collected by the compiler is being overwritten"); } } if (TraceDeoptimization) { tty->print_cr("Saving speculation to speculation log"); } - SpeculationLog::set_lastFailed(speculation_log, speculation); + HotSpotSpeculationLog::set_lastFailed(speculation_log, speculation); } else { if (TraceDeoptimization) { tty->print_cr("Speculation present but no speculation log"); @@ -2062,6 +2062,7 @@ int Deoptimization::trap_state_set_recompiled(int trap_state, bool z) { // This is used for debugging and diagnostics, including LogFile output. const char* Deoptimization::format_trap_state(char* buf, size_t buflen, int trap_state) { + assert(buflen > 0, "sanity"); DeoptReason reason = trap_state_reason(trap_state); bool recomp_flag = trap_state_is_recompiled(trap_state); // Re-encode the state from its decoded components. @@ -2082,8 +2083,6 @@ const char* Deoptimization::format_trap_state(char* buf, size_t buflen, trap_reason_name(reason), recomp_flag ? " recompiled" : ""); } - if (len >= buflen) - buf[buflen-1] = '\0'; return buf; } @@ -2178,8 +2177,6 @@ const char* Deoptimization::format_trap_request(char* buf, size_t buflen, #endif ); } - if (len >= buflen) - buf[buflen-1] = '\0'; return buf; } diff --git a/hotspot/src/share/vm/runtime/deoptimization.hpp b/hotspot/src/share/vm/runtime/deoptimization.hpp index e02836849b6..b61c3506668 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.hpp +++ b/hotspot/src/share/vm/runtime/deoptimization.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -420,8 +420,8 @@ JVMCI_ONLY(public:) bool& ret_maybe_prior_trap, bool& ret_maybe_prior_recompile); // class loading support for uncommon trap - static void load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS); - static void load_class_by_index(constantPoolHandle constant_pool, int index); + static void load_class_by_index(const constantPoolHandle& constant_pool, int index, TRAPS); + static void load_class_by_index(const constantPoolHandle& constant_pool, int index); static UnrollBlock* fetch_unroll_info_helper(JavaThread* thread); diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 0b208d249d9..cbd63cd20b2 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -442,6 +442,14 @@ class FrameValue VALUE_OBJ_CLASS_SPEC { char* description; int owner; int priority; + + FrameValue() { + location = NULL; + description = NULL; + owner = -1; + priority = 0; + } + }; diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 3357fcfc323..9d74dd36c69 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -306,35 +306,36 @@ void Flag::unlock_diagnostic() { _flags = Flags(_flags & ~KIND_DIAGNOSTIC); } -// Get custom message for this locked flag, or return NULL if -// none is available. -void Flag::get_locked_message(char* buf, int buflen) const { +// Get custom message for this locked flag, or NULL if +// none is available. Returns message type produced. +Flag::MsgType Flag::get_locked_message(char* buf, int buflen) const { buf[0] = '\0'; if (is_diagnostic() && !is_unlocked()) { jio_snprintf(buf, buflen, "Error: VM option '%s' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.\n" "Error: The unlock option must precede '%s'.\n", _name, _name); - return; + return Flag::DIAGNOSTIC_FLAG_BUT_LOCKED; } if (is_experimental() && !is_unlocked()) { jio_snprintf(buf, buflen, "Error: VM option '%s' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.\n" "Error: The unlock option must precede '%s'.\n", _name, _name); - return; + return Flag::EXPERIMENTAL_FLAG_BUT_LOCKED; } if (is_develop() && is_product_build()) { jio_snprintf(buf, buflen, "Error: VM option '%s' is develop and is available only in debug version of VM.\n", _name); - return; + return Flag::DEVELOPER_FLAG_BUT_PRODUCT_BUILD; } if (is_notproduct() && is_product_build()) { jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n", _name); - return; + return Flag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD; } get_locked_message_ext(buf, buflen); + return Flag::NONE; } bool Flag::is_writeable() const { @@ -348,11 +349,6 @@ bool Flag::is_external() const { return is_manageable() || is_external_ext(); } - -// Length of format string (e.g. "%.1234s") for printing ccstr below -#define FORMAT_BUFFER_LEN 16 - -PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL void Flag::print_on(outputStream* st, bool withComments, bool printRanges) { // Don't print notproduct and develop flags in a product build. if (is_constant_in_binary()) { @@ -384,14 +380,8 @@ void Flag::print_on(outputStream* st, bool withComments, bool printRanges) { if (cp != NULL) { const char* eol; while ((eol = strchr(cp, '\n')) != NULL) { - char format_buffer[FORMAT_BUFFER_LEN]; size_t llen = pointer_delta(eol, cp, sizeof(char)); - jio_snprintf(format_buffer, FORMAT_BUFFER_LEN, - "%%." SIZE_FORMAT "s", llen); - PRAGMA_DIAG_PUSH - PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL - st->print(format_buffer, cp); - PRAGMA_DIAG_POP + st->print("%.*s", (int)llen, cp); st->cr(); cp = eol+1; st->print("%5s %-35s += ", "", _name); @@ -797,7 +787,7 @@ static void trace_flag_changed(const char* name, const T old_value, const T new_ e.commit(); } -static Flag::Error apply_constraint_and_check_range_bool(const char* name, bool new_value, bool verbose = true) { +static Flag::Error apply_constraint_and_check_range_bool(const char* name, bool new_value, bool verbose) { Flag::Error status = Flag::SUCCESS; CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name); if (constraint != NULL) { @@ -814,32 +804,33 @@ Flag::Error CommandLineFlags::boolAt(const char* name, size_t len, bool* value, return Flag::SUCCESS; } -Flag::Error CommandLineFlags::boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin) { - Flag* result = Flag::find_flag(name, len); - if (result == NULL) return Flag::INVALID_FLAG; - if (!result->is_bool()) return Flag::WRONG_FORMAT; +Flag::Error CommandLineFlags::boolAtPut(Flag* flag, bool* value, Flag::Flags origin) { + const char* name; + if (flag == NULL) return Flag::INVALID_FLAG; + if (!flag->is_bool()) return Flag::WRONG_FORMAT; + name = flag->_name; Flag::Error check = apply_constraint_and_check_range_bool(name, *value, !CommandLineFlagConstraintList::validated_after_ergo()); if (check != Flag::SUCCESS) return check; - bool old_value = result->get_bool(); + bool old_value = flag->get_bool(); trace_flag_changed(name, old_value, *value, origin); - result->set_bool(*value); + flag->set_bool(*value); *value = old_value; - result->set_origin(origin); + flag->set_origin(origin); return Flag::SUCCESS; } +Flag::Error CommandLineFlags::boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin) { + Flag* result = Flag::find_flag(name, len); + return boolAtPut(result, value, origin); +} + Flag::Error CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin) { Flag* faddr = address_of_flag(flag); guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type"); - Flag::Error check = apply_constraint_and_check_range_bool(faddr->_name, value); - if (check != Flag::SUCCESS) return check; - trace_flag_changed(faddr->_name, faddr->get_bool(), value, origin); - faddr->set_bool(value); - faddr->set_origin(origin); - return Flag::SUCCESS; + return CommandLineFlags::boolAtPut(faddr, &value, origin); } -static Flag::Error apply_constraint_and_check_range_int(const char* name, int new_value, bool verbose = true) { +static Flag::Error apply_constraint_and_check_range_int(const char* name, int new_value, bool verbose) { Flag::Error status = Flag::SUCCESS; CommandLineFlagRange* range = CommandLineFlagRangeList::find(name); if (range != NULL) { @@ -862,32 +853,33 @@ Flag::Error CommandLineFlags::intAt(const char* name, size_t len, int* value, bo return Flag::SUCCESS; } -Flag::Error CommandLineFlags::intAtPut(const char* name, size_t len, int* value, Flag::Flags origin) { - Flag* result = Flag::find_flag(name, len); - if (result == NULL) return Flag::INVALID_FLAG; - if (!result->is_int()) return Flag::WRONG_FORMAT; +Flag::Error CommandLineFlags::intAtPut(Flag* flag, int* value, Flag::Flags origin) { + const char* name; + if (flag == NULL) return Flag::INVALID_FLAG; + if (!flag->is_int()) return Flag::WRONG_FORMAT; + name = flag->_name; Flag::Error check = apply_constraint_and_check_range_int(name, *value, !CommandLineFlagConstraintList::validated_after_ergo()); if (check != Flag::SUCCESS) return check; - int old_value = result->get_int(); + int old_value = flag->get_int(); trace_flag_changed(name, old_value, *value, origin); - result->set_int(*value); + flag->set_int(*value); *value = old_value; - result->set_origin(origin); + flag->set_origin(origin); return Flag::SUCCESS; } +Flag::Error CommandLineFlags::intAtPut(const char* name, size_t len, int* value, Flag::Flags origin) { + Flag* result = Flag::find_flag(name, len); + return intAtPut(result, value, origin); +} + Flag::Error CommandLineFlagsEx::intAtPut(CommandLineFlagWithType flag, int value, Flag::Flags origin) { Flag* faddr = address_of_flag(flag); guarantee(faddr != NULL && faddr->is_int(), "wrong flag type"); - Flag::Error check = apply_constraint_and_check_range_int(faddr->_name, value, !CommandLineFlagConstraintList::validated_after_ergo()); - if (check != Flag::SUCCESS) return check; - trace_flag_changed(faddr->_name, faddr->get_int(), value, origin); - faddr->set_int(value); - faddr->set_origin(origin); - return Flag::SUCCESS; + return CommandLineFlags::intAtPut(faddr, &value, origin); } -static Flag::Error apply_constraint_and_check_range_uint(const char* name, uint new_value, bool verbose = true) { +static Flag::Error apply_constraint_and_check_range_uint(const char* name, uint new_value, bool verbose) { Flag::Error status = Flag::SUCCESS; CommandLineFlagRange* range = CommandLineFlagRangeList::find(name); if (range != NULL) { @@ -910,29 +902,30 @@ Flag::Error CommandLineFlags::uintAt(const char* name, size_t len, uint* value, return Flag::SUCCESS; } -Flag::Error CommandLineFlags::uintAtPut(const char* name, size_t len, uint* value, Flag::Flags origin) { - Flag* result = Flag::find_flag(name, len); - if (result == NULL) return Flag::INVALID_FLAG; - if (!result->is_uint()) return Flag::WRONG_FORMAT; +Flag::Error CommandLineFlags::uintAtPut(Flag* flag, uint* value, Flag::Flags origin) { + const char* name; + if (flag == NULL) return Flag::INVALID_FLAG; + if (!flag->is_uint()) return Flag::WRONG_FORMAT; + name = flag->_name; Flag::Error check = apply_constraint_and_check_range_uint(name, *value, !CommandLineFlagConstraintList::validated_after_ergo()); if (check != Flag::SUCCESS) return check; - uint old_value = result->get_uint(); + uint old_value = flag->get_uint(); trace_flag_changed(name, old_value, *value, origin); - result->set_uint(*value); + flag->set_uint(*value); *value = old_value; - result->set_origin(origin); + flag->set_origin(origin); return Flag::SUCCESS; } +Flag::Error CommandLineFlags::uintAtPut(const char* name, size_t len, uint* value, Flag::Flags origin) { + Flag* result = Flag::find_flag(name, len); + return uintAtPut(result, value, origin); +} + Flag::Error CommandLineFlagsEx::uintAtPut(CommandLineFlagWithType flag, uint value, Flag::Flags origin) { Flag* faddr = address_of_flag(flag); guarantee(faddr != NULL && faddr->is_uint(), "wrong flag type"); - Flag::Error check = apply_constraint_and_check_range_uint(faddr->_name, value, !CommandLineFlagConstraintList::validated_after_ergo()); - if (check != Flag::SUCCESS) return check; - trace_flag_changed(faddr->_name, faddr->get_uint(), value, origin); - faddr->set_uint(value); - faddr->set_origin(origin); - return Flag::SUCCESS; + return CommandLineFlags::uintAtPut(faddr, &value, origin); } Flag::Error CommandLineFlags::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) { @@ -943,7 +936,7 @@ Flag::Error CommandLineFlags::intxAt(const char* name, size_t len, intx* value, return Flag::SUCCESS; } -static Flag::Error apply_constraint_and_check_range_intx(const char* name, intx new_value, bool verbose = true) { +static Flag::Error apply_constraint_and_check_range_intx(const char* name, intx new_value, bool verbose) { Flag::Error status = Flag::SUCCESS; CommandLineFlagRange* range = CommandLineFlagRangeList::find(name); if (range != NULL) { @@ -958,29 +951,30 @@ static Flag::Error apply_constraint_and_check_range_intx(const char* name, intx return status; } -Flag::Error CommandLineFlags::intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin) { - Flag* result = Flag::find_flag(name, len); - if (result == NULL) return Flag::INVALID_FLAG; - if (!result->is_intx()) return Flag::WRONG_FORMAT; +Flag::Error CommandLineFlags::intxAtPut(Flag* flag, intx* value, Flag::Flags origin) { + const char* name; + if (flag == NULL) return Flag::INVALID_FLAG; + if (!flag->is_intx()) return Flag::WRONG_FORMAT; + name = flag->_name; Flag::Error check = apply_constraint_and_check_range_intx(name, *value, !CommandLineFlagConstraintList::validated_after_ergo()); if (check != Flag::SUCCESS) return check; - intx old_value = result->get_intx(); + intx old_value = flag->get_intx(); trace_flag_changed(name, old_value, *value, origin); - result->set_intx(*value); + flag->set_intx(*value); *value = old_value; - result->set_origin(origin); + flag->set_origin(origin); return Flag::SUCCESS; } +Flag::Error CommandLineFlags::intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin) { + Flag* result = Flag::find_flag(name, len); + return intxAtPut(result, value, origin); +} + Flag::Error CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin) { Flag* faddr = address_of_flag(flag); guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type"); - Flag::Error check = apply_constraint_and_check_range_intx(faddr->_name, value); - if (check != Flag::SUCCESS) return check; - trace_flag_changed(faddr->_name, faddr->get_intx(), value, origin); - faddr->set_intx(value); - faddr->set_origin(origin); - return Flag::SUCCESS; + return CommandLineFlags::intxAtPut(faddr, &value, origin); } Flag::Error CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) { @@ -991,7 +985,7 @@ Flag::Error CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value return Flag::SUCCESS; } -static Flag::Error apply_constraint_and_check_range_uintx(const char* name, uintx new_value, bool verbose = true) { +static Flag::Error apply_constraint_and_check_range_uintx(const char* name, uintx new_value, bool verbose) { Flag::Error status = Flag::SUCCESS; CommandLineFlagRange* range = CommandLineFlagRangeList::find(name); if (range != NULL) { @@ -1006,29 +1000,30 @@ static Flag::Error apply_constraint_and_check_range_uintx(const char* name, uint return status; } -Flag::Error CommandLineFlags::uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin) { - Flag* result = Flag::find_flag(name, len); - if (result == NULL) return Flag::INVALID_FLAG; - if (!result->is_uintx()) return Flag::WRONG_FORMAT; +Flag::Error CommandLineFlags::uintxAtPut(Flag* flag, uintx* value, Flag::Flags origin) { + const char* name; + if (flag == NULL) return Flag::INVALID_FLAG; + if (!flag->is_uintx()) return Flag::WRONG_FORMAT; + name = flag->_name; Flag::Error check = apply_constraint_and_check_range_uintx(name, *value, !CommandLineFlagConstraintList::validated_after_ergo()); if (check != Flag::SUCCESS) return check; - uintx old_value = result->get_uintx(); + uintx old_value = flag->get_uintx(); trace_flag_changed(name, old_value, *value, origin); - result->set_uintx(*value); + flag->set_uintx(*value); *value = old_value; - result->set_origin(origin); + flag->set_origin(origin); return Flag::SUCCESS; } +Flag::Error CommandLineFlags::uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin) { + Flag* result = Flag::find_flag(name, len); + return uintxAtPut(result, value, origin); +} + Flag::Error CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin) { Flag* faddr = address_of_flag(flag); guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type"); - Flag::Error check = apply_constraint_and_check_range_uintx(faddr->_name, value); - if (check != Flag::SUCCESS) return check; - trace_flag_changed(faddr->_name, faddr->get_uintx(), value, origin); - faddr->set_uintx(value); - faddr->set_origin(origin); - return Flag::SUCCESS; + return CommandLineFlags::uintxAtPut(faddr, &value, origin); } Flag::Error CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) { @@ -1039,7 +1034,7 @@ Flag::Error CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* return Flag::SUCCESS; } -static Flag::Error apply_constraint_and_check_range_uint64_t(const char* name, uint64_t new_value, bool verbose = true) { +static Flag::Error apply_constraint_and_check_range_uint64_t(const char* name, uint64_t new_value, bool verbose) { Flag::Error status = Flag::SUCCESS; CommandLineFlagRange* range = CommandLineFlagRangeList::find(name); if (range != NULL) { @@ -1054,29 +1049,30 @@ static Flag::Error apply_constraint_and_check_range_uint64_t(const char* name, u return status; } -Flag::Error CommandLineFlags::uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin) { - Flag* result = Flag::find_flag(name, len); - if (result == NULL) return Flag::INVALID_FLAG; - if (!result->is_uint64_t()) return Flag::WRONG_FORMAT; +Flag::Error CommandLineFlags::uint64_tAtPut(Flag* flag, uint64_t* value, Flag::Flags origin) { + const char* name; + if (flag == NULL) return Flag::INVALID_FLAG; + if (!flag->is_uint64_t()) return Flag::WRONG_FORMAT; + name = flag->_name; Flag::Error check = apply_constraint_and_check_range_uint64_t(name, *value, !CommandLineFlagConstraintList::validated_after_ergo()); if (check != Flag::SUCCESS) return check; - uint64_t old_value = result->get_uint64_t(); + uint64_t old_value = flag->get_uint64_t(); trace_flag_changed(name, old_value, *value, origin); - result->set_uint64_t(*value); + flag->set_uint64_t(*value); *value = old_value; - result->set_origin(origin); + flag->set_origin(origin); return Flag::SUCCESS; } +Flag::Error CommandLineFlags::uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin) { + Flag* result = Flag::find_flag(name, len); + return uint64_tAtPut(result, value, origin); +} + Flag::Error CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin) { Flag* faddr = address_of_flag(flag); guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type"); - Flag::Error check = apply_constraint_and_check_range_uint64_t(faddr->_name, value); - if (check != Flag::SUCCESS) return check; - trace_flag_changed(faddr->_name, faddr->get_uint64_t(), value, origin); - faddr->set_uint64_t(value); - faddr->set_origin(origin); - return Flag::SUCCESS; + return CommandLineFlags::uint64_tAtPut(faddr, &value, origin); } Flag::Error CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) { @@ -1087,7 +1083,7 @@ Flag::Error CommandLineFlags::size_tAt(const char* name, size_t len, size_t* val return Flag::SUCCESS; } -static Flag::Error apply_constraint_and_check_range_size_t(const char* name, size_t new_value, bool verbose = true) { +static Flag::Error apply_constraint_and_check_range_size_t(const char* name, size_t new_value, bool verbose) { Flag::Error status = Flag::SUCCESS; CommandLineFlagRange* range = CommandLineFlagRangeList::find(name); if (range != NULL) { @@ -1102,29 +1098,31 @@ static Flag::Error apply_constraint_and_check_range_size_t(const char* name, siz return status; } -Flag::Error CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin) { - Flag* result = Flag::find_flag(name, len); - if (result == NULL) return Flag::INVALID_FLAG; - if (!result->is_size_t()) return Flag::WRONG_FORMAT; + +Flag::Error CommandLineFlags::size_tAtPut(Flag* flag, size_t* value, Flag::Flags origin) { + const char* name; + if (flag == NULL) return Flag::INVALID_FLAG; + if (!flag->is_size_t()) return Flag::WRONG_FORMAT; + name = flag->_name; Flag::Error check = apply_constraint_and_check_range_size_t(name, *value, !CommandLineFlagConstraintList::validated_after_ergo()); if (check != Flag::SUCCESS) return check; - size_t old_value = result->get_size_t(); + size_t old_value = flag->get_size_t(); trace_flag_changed(name, old_value, *value, origin); - result->set_size_t(*value); + flag->set_size_t(*value); *value = old_value; - result->set_origin(origin); + flag->set_origin(origin); return Flag::SUCCESS; } +Flag::Error CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin) { + Flag* result = Flag::find_flag(name, len); + return size_tAtPut(result, value, origin); +} + Flag::Error CommandLineFlagsEx::size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin) { Flag* faddr = address_of_flag(flag); guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type"); - Flag::Error check = apply_constraint_and_check_range_size_t(faddr->_name, value); - if (check != Flag::SUCCESS) return check; - trace_flag_changed(faddr->_name, faddr->get_size_t(), value, origin); - faddr->set_size_t(value); - faddr->set_origin(origin); - return Flag::SUCCESS; + return CommandLineFlags::size_tAtPut(faddr, &value, origin); } Flag::Error CommandLineFlags::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) { @@ -1135,7 +1133,7 @@ Flag::Error CommandLineFlags::doubleAt(const char* name, size_t len, double* val return Flag::SUCCESS; } -static Flag::Error apply_constraint_and_check_range_double(const char* name, double new_value, bool verbose = true) { +static Flag::Error apply_constraint_and_check_range_double(const char* name, double new_value, bool verbose) { Flag::Error status = Flag::SUCCESS; CommandLineFlagRange* range = CommandLineFlagRangeList::find(name); if (range != NULL) { @@ -1150,29 +1148,30 @@ static Flag::Error apply_constraint_and_check_range_double(const char* name, dou return status; } -Flag::Error CommandLineFlags::doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin) { - Flag* result = Flag::find_flag(name, len); - if (result == NULL) return Flag::INVALID_FLAG; - if (!result->is_double()) return Flag::WRONG_FORMAT; +Flag::Error CommandLineFlags::doubleAtPut(Flag* flag, double* value, Flag::Flags origin) { + const char* name; + if (flag == NULL) return Flag::INVALID_FLAG; + if (!flag->is_double()) return Flag::WRONG_FORMAT; + name = flag->_name; Flag::Error check = apply_constraint_and_check_range_double(name, *value, !CommandLineFlagConstraintList::validated_after_ergo()); if (check != Flag::SUCCESS) return check; - double old_value = result->get_double(); + double old_value = flag->get_double(); trace_flag_changed(name, old_value, *value, origin); - result->set_double(*value); + flag->set_double(*value); *value = old_value; - result->set_origin(origin); + flag->set_origin(origin); return Flag::SUCCESS; } +Flag::Error CommandLineFlags::doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin) { + Flag* result = Flag::find_flag(name, len); + return doubleAtPut(result, value, origin); +} + Flag::Error CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin) { Flag* faddr = address_of_flag(flag); guarantee(faddr != NULL && faddr->is_double(), "wrong flag type"); - Flag::Error check = apply_constraint_and_check_range_double(faddr->_name, value); - if (check != Flag::SUCCESS) return check; - trace_flag_changed(faddr->_name, faddr->get_double(), value, origin); - faddr->set_double(value); - faddr->set_origin(origin); - return Flag::SUCCESS; + return CommandLineFlags::doubleAtPut(faddr, &value, origin); } Flag::Error CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) { diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 169316cd77e..2ff157f5368 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -282,6 +282,14 @@ struct Flag { ERR_OTHER }; + enum MsgType { + NONE = 0, + DIAGNOSTIC_FLAG_BUT_LOCKED, + EXPERIMENTAL_FLAG_BUT_LOCKED, + DEVELOPER_FLAG_BUT_PRODUCT_BUILD, + NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD + }; + const char* _type; const char* _name; void* _addr; @@ -367,7 +375,7 @@ struct Flag { void unlock_diagnostic(); - void get_locked_message(char*, int) const; + Flag::MsgType get_locked_message(char*, int) const; void get_locked_message_ext(char*, int) const; // printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges @@ -444,41 +452,49 @@ class CommandLineFlags { public: static Flag::Error boolAt(const char* name, size_t len, bool* value, bool allow_locked = false, bool return_flag = false); static Flag::Error boolAt(const char* name, bool* value, bool allow_locked = false, bool return_flag = false) { return boolAt(name, strlen(name), value, allow_locked, return_flag); } + static Flag::Error boolAtPut(Flag* flag, bool* value, Flag::Flags origin); static Flag::Error boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin); static Flag::Error boolAtPut(const char* name, bool* value, Flag::Flags origin) { return boolAtPut(name, strlen(name), value, origin); } static Flag::Error intAt(const char* name, size_t len, int* value, bool allow_locked = false, bool return_flag = false); static Flag::Error intAt(const char* name, int* value, bool allow_locked = false, bool return_flag = false) { return intAt(name, strlen(name), value, allow_locked, return_flag); } + static Flag::Error intAtPut(Flag* flag, int* value, Flag::Flags origin); static Flag::Error intAtPut(const char* name, size_t len, int* value, Flag::Flags origin); static Flag::Error intAtPut(const char* name, int* value, Flag::Flags origin) { return intAtPut(name, strlen(name), value, origin); } static Flag::Error uintAt(const char* name, size_t len, uint* value, bool allow_locked = false, bool return_flag = false); static Flag::Error uintAt(const char* name, uint* value, bool allow_locked = false, bool return_flag = false) { return uintAt(name, strlen(name), value, allow_locked, return_flag); } + static Flag::Error uintAtPut(Flag* flag, uint* value, Flag::Flags origin); static Flag::Error uintAtPut(const char* name, size_t len, uint* value, Flag::Flags origin); static Flag::Error uintAtPut(const char* name, uint* value, Flag::Flags origin) { return uintAtPut(name, strlen(name), value, origin); } static Flag::Error intxAt(const char* name, size_t len, intx* value, bool allow_locked = false, bool return_flag = false); static Flag::Error intxAt(const char* name, intx* value, bool allow_locked = false, bool return_flag = false) { return intxAt(name, strlen(name), value, allow_locked, return_flag); } + static Flag::Error intxAtPut(Flag* flag, intx* value, Flag::Flags origin); static Flag::Error intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin); static Flag::Error intxAtPut(const char* name, intx* value, Flag::Flags origin) { return intxAtPut(name, strlen(name), value, origin); } static Flag::Error uintxAt(const char* name, size_t len, uintx* value, bool allow_locked = false, bool return_flag = false); static Flag::Error uintxAt(const char* name, uintx* value, bool allow_locked = false, bool return_flag = false) { return uintxAt(name, strlen(name), value, allow_locked, return_flag); } + static Flag::Error uintxAtPut(Flag* flag, uintx* value, Flag::Flags origin); static Flag::Error uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin); static Flag::Error uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); } static Flag::Error size_tAt(const char* name, size_t len, size_t* value, bool allow_locked = false, bool return_flag = false); static Flag::Error size_tAt(const char* name, size_t* value, bool allow_locked = false, bool return_flag = false) { return size_tAt(name, strlen(name), value, allow_locked, return_flag); } + static Flag::Error size_tAtPut(Flag* flag, size_t* value, Flag::Flags origin); static Flag::Error size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin); static Flag::Error size_tAtPut(const char* name, size_t* value, Flag::Flags origin) { return size_tAtPut(name, strlen(name), value, origin); } static Flag::Error uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked = false, bool return_flag = false); static Flag::Error uint64_tAt(const char* name, uint64_t* value, bool allow_locked = false, bool return_flag = false) { return uint64_tAt(name, strlen(name), value, allow_locked, return_flag); } + static Flag::Error uint64_tAtPut(Flag* flag, uint64_t* value, Flag::Flags origin); static Flag::Error uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin); static Flag::Error uint64_tAtPut(const char* name, uint64_t* value, Flag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); } static Flag::Error doubleAt(const char* name, size_t len, double* value, bool allow_locked = false, bool return_flag = false); static Flag::Error doubleAt(const char* name, double* value, bool allow_locked = false, bool return_flag = false) { return doubleAt(name, strlen(name), value, allow_locked, return_flag); } + static Flag::Error doubleAtPut(Flag* flag, double* value, Flag::Flags origin); static Flag::Error doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin); static Flag::Error doubleAtPut(const char* name, double* value, Flag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); } @@ -804,7 +820,7 @@ public: "Inline Thread.currentThread, etc") \ \ develop(bool, InlineUnsafeOps, true, \ - "Inline memory ops (native methods) from sun.misc.Unsafe") \ + "Inline memory ops (native methods) from Unsafe") \ \ product(bool, CriticalJNINatives, true, \ "Check for critical JNI entry points") \ @@ -1325,9 +1341,6 @@ public: product(bool, AllowJNIEnvProxy, false, \ "Allow JNIEnv proxies for jdbx") \ \ - product(bool, JNIDetachReleasesMonitors, true, \ - "JNI DetachCurrentThread releases monitors owned by thread") \ - \ product(bool, RestoreMXCSROnJNICalls, false, \ "Restore MXCSR when returning from JNI calls") \ \ @@ -1493,9 +1506,6 @@ public: develop(bool, TraceOopMapRewrites, false, \ "Trace rewriting of method oops during oop map generation") \ \ - develop(bool, TraceSafepoint, false, \ - "Trace safepoint operations") \ - \ develop(bool, TraceICBuffer, false, \ "Trace usage of IC buffer") \ \ @@ -1622,12 +1632,6 @@ public: "Number of times to retry allocations when " \ "blocked by the GC locker") \ \ - develop(bool, UseCMSAdaptiveFreeLists, true, \ - "Use adaptive free lists in the CMS generation") \ - \ - develop(bool, UseAsyncConcMarkSweepGC, true, \ - "Use Asynchronous Concurrent Mark-Sweep GC in the old generation")\ - \ product(bool, UseCMSBestFit, true, \ "Use CMS best fit allocation strategy") \ \ @@ -1822,10 +1826,6 @@ public: "When CMS class unloading is enabled, the maximum CMS cycle " \ "count for which classes may not be unloaded") \ \ - develop(intx, CMSDictionaryChoice, 0, \ - "Use BinaryTreeDictionary as default in the CMS generation") \ - range(0, 2) \ - \ product(uintx, CMSIndexedFreeListReplenish, 4, \ "Replenish an indexed free list with this number of chunks") \ range(1, max_uintx) \ @@ -1840,9 +1840,6 @@ public: product(bool, CMSLoopWarn, false, \ "Warn in case of excessive CMS looping") \ \ - develop(bool, CMSOverflowEarlyRestoration, false, \ - "Restore preserved marks early") \ - \ /* where does the range max value of (max_jint - 1) come from? */ \ product(size_t, MarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M), \ "Maximum size of marking stack") \ @@ -2889,6 +2886,9 @@ public: product(bool, AggressiveOpts, false, \ "Enable aggressive optimizations - see arguments.cpp") \ \ + product_pd(bool, CompactStrings, \ + "Enable Strings to use single byte chars in backing store") \ + \ product_pd(uintx, TypeProfileLevel, \ "=XYZ, with Z: Type profiling of arguments at call; " \ "Y: Type profiling of return value at call; " \ @@ -3097,6 +3097,7 @@ public: \ product(intx, AllocatePrefetchStepSize, 16, \ "Step size in bytes of sequential prefetch instructions") \ + range(1, max_jint) \ constraint(AllocatePrefetchStepSizeConstraintFunc,AfterMemoryInit)\ \ product(intx, AllocatePrefetchInstr, 0, \ @@ -3580,6 +3581,7 @@ public: \ product_pd(intx, OptoLoopAlignment, \ "Align inner loops to zero relative to this modulus") \ + range(1, 16) \ constraint(OptoLoopAlignmentConstraintFunc, AfterErgo) \ \ product_pd(uintx, InitialCodeCacheSize, \ @@ -3744,6 +3746,7 @@ public: product(intx, CompilerThreadPriority, -1, \ "The native priority at which compiler threads should run " \ "(-1 means no change)") \ + range(min_jint, max_jint) \ constraint(CompilerThreadPriorityConstraintFunc, AfterErgo) \ \ product(intx, VMThreadPriority, -1, \ @@ -4209,9 +4212,6 @@ public: diagnostic(bool, StringDeduplicationRehashALot, false, \ "Force table rehash every time the table is scanned") \ \ - develop(bool, TraceDefaultMethods, false, \ - "Trace the default method processing steps") \ - \ diagnostic(bool, WhiteBoxAPI, false, \ "Enable internal testing APIs") \ \ @@ -4253,7 +4253,7 @@ public: "Use locked-tracing when doing event-based tracing") \ \ diagnostic(bool, UseUnalignedAccesses, false, \ - "Use unaligned memory accesses in sun.misc.Unsafe") \ + "Use unaligned memory accesses in Unsafe") \ \ product_pd(bool, PreserveFramePointer, \ "Use the FP register for holding the frame pointer " \ diff --git a/hotspot/src/share/vm/runtime/handles.cpp b/hotspot/src/share/vm/runtime/handles.cpp index 08e04e41470..98ff1ffc424 100644 --- a/hotspot/src/share/vm/runtime/handles.cpp +++ b/hotspot/src/share/vm/runtime/handles.cpp @@ -212,7 +212,8 @@ ResetNoHandleMark::~ResetNoHandleMark() { } bool instanceKlassHandle::is_instanceKlass(const Klass* k) { - return k->oop_is_instance(); + // Need this to avoid circular include dependency + return k->is_instance_klass(); } #endif diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index d1d3d34adf7..35bb7684be8 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -575,6 +575,11 @@ void vm_shutdown() void vm_abort(bool dump_core) { vm_perform_shutdown_actions(); os::wait_for_keypress_at_exit(); + + // Flush stdout and stderr before abort. + fflush(stdout); + fflush(stderr); + os::abort(dump_core); ShouldNotReachHere(); } diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp index c94e9d24f6a..9acd0200b29 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.cpp +++ b/hotspot/src/share/vm/runtime/javaCalls.cpp @@ -289,21 +289,20 @@ void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, // Implementation of JavaCalls (low level) -void JavaCalls::call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS) { +void JavaCalls::call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) { // Check if we need to wrap a potential OS exception handler around thread // This is used for e.g. Win32 structured exception handlers assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls"); // Need to wrap each and every time, since there might be native code down the // stack that has installed its own exception handlers - os::os_exception_wrapper(call_helper, result, &method, args, THREAD); + os::os_exception_wrapper(call_helper, result, method, args, THREAD); } -void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) { +void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) { // During dumping, Java execution environment is not fully initialized. Also, Java execution // may cause undesirable side-effects in the class metadata. assert(!DumpSharedSpaces, "must not execute Java bytecodes when dumping"); - methodHandle method = *m; JavaThread* thread = (JavaThread*)THREAD; assert(thread->is_Java_thread(), "must be called by a java thread"); assert(method.not_null(), "must have a method to call"); @@ -546,7 +545,7 @@ class SignatureChekker : public SignatureIterator { }; -void JavaCallArguments::verify(methodHandle method, BasicType return_type, +void JavaCallArguments::verify(const methodHandle& method, BasicType return_type, Thread *thread) { guarantee(method->size_of_parameters() == size_of_parameters(), "wrong no. of arguments pushed"); diff --git a/hotspot/src/share/vm/runtime/javaCalls.hpp b/hotspot/src/share/vm/runtime/javaCalls.hpp index 9ac2c9a5ea4..543e58f0dde 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.hpp +++ b/hotspot/src/share/vm/runtime/javaCalls.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -189,7 +189,7 @@ class JavaCallArguments : public StackObj { int size_of_parameters() const { return _size; } // Verify that pushed arguments fits a given method - void verify(methodHandle method, BasicType return_type, Thread *thread); + void verify(const methodHandle& method, BasicType return_type, Thread *thread); }; // All calls to Java have to go via JavaCalls. Sets up the stack frame @@ -197,7 +197,7 @@ class JavaCallArguments : public StackObj { // class JavaCalls: AllStatic { - static void call_helper(JavaValue* result, methodHandle* method, JavaCallArguments* args, TRAPS); + static void call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS); public: // call_special // ------------ @@ -227,7 +227,7 @@ class JavaCalls: AllStatic { static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS); // Low-level interface - static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS); + static void call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS); }; #endif // SHARE_VM_RUNTIME_JAVACALLS_HPP diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 32e4b0942fb..d1cc3d76074 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -32,6 +32,7 @@ #include "code/vtableStubs.hpp" #include "gc/shared/vmGCOperations.hpp" #include "interpreter/interpreter.hpp" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #ifdef ASSERT #include "memory/guardedMemory.hpp" @@ -96,8 +97,7 @@ char* os::iso8601_time(char* buffer, size_t buffer_length) { // Output will be of the form "YYYY-MM-DDThh:mm:ss.mmm+zzzz\0" // 1 2 // 12345678901234567890123456789 - static const char* iso8601_format = - "%04d-%02d-%02dT%02d:%02d:%02d.%03d%c%02d%02d"; + // format string: "%04d-%02d-%02dT%02d:%02d:%02d.%03d%c%02d%02d" static const size_t needed_buffer = 29; // Sanity check the arguments @@ -158,7 +158,8 @@ char* os::iso8601_time(char* buffer, size_t buffer_length) { // Print an ISO 8601 date and time stamp into the buffer const int year = 1900 + time_struct.tm_year; const int month = 1 + time_struct.tm_mon; - const int printed = jio_snprintf(buffer, buffer_length, iso8601_format, + const int printed = jio_snprintf(buffer, buffer_length, + "%04d-%02d-%02dT%02d:%02d:%02d.%03d%c%02d%02d", year, month, time_struct.tm_mday, @@ -1363,9 +1364,8 @@ static volatile intptr_t SerializePageLock = 0; // thread tries to store to the "read-only" memory serialize page during state // transition. void os::block_on_serialize_page_trap() { - if (TraceSafepoint) { - tty->print_cr("Block until the serialize page permission restored"); - } + log_debug(safepoint)("Block until the serialize page permission restored"); + // When VMThread is holding the SerializePageLock during modifying the // access permission of the memory serialize page, the following call // will block until the permission of that page is restored to rw. @@ -1394,7 +1394,7 @@ void os::serialize_thread_states() { // Returns true if the current stack pointer is above the stack shadow // pages, false otherwise. -bool os::stack_shadow_pages_available(Thread *thread, methodHandle method) { +bool os::stack_shadow_pages_available(Thread *thread, const methodHandle& method) { assert(StackRedPages > 0 && StackYellowPages > 0,"Sanity check"); address sp = current_stack_pointer(); // Check if we have StackShadowPages above the yellow zone. This parameter diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 8cca98661c2..f9b920ee822 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -96,7 +96,7 @@ enum ThreadPriority { // JLS 20.20.1-3 const bool ExecMem = true; // Typedef for structured exception handling support -typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread); +typedef void (*java_call_t)(JavaValue* value, const methodHandle& method, JavaCallArguments* args, Thread* thread); class MallocTracker; @@ -263,7 +263,7 @@ class os: AllStatic { static bool uses_stack_guard_pages(); static bool allocate_stack_guard_pages(); static void bang_stack_shadow_pages(); - static bool stack_shadow_pages_available(Thread *thread, methodHandle method); + static bool stack_shadow_pages_available(Thread *thread, const methodHandle& method); // OS interface to Virtual Memory @@ -589,6 +589,9 @@ class os: AllStatic { static void *find_agent_function(AgentLibrary *agent_lib, bool check_lib, const char *syms[], size_t syms_len); + // Write to stream + static int log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) ATTRIBUTE_PRINTF(3, 0); + // Print out system information; they are called by fatal error handler. // Output format may be different on different platforms. static void print_os_info(outputStream* st); @@ -722,7 +725,7 @@ class os: AllStatic { static void init_random(long initval); // initialize random sequence // Structured OS Exception support - static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread); + static void os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& method, JavaCallArguments* args, Thread* thread); // On Posix compatible OS it will simply check core dump limits while on Windows // it will check if dump file can be created. Check or prepare a core dump to be diff --git a/hotspot/src/share/vm/runtime/park.hpp b/hotspot/src/share/vm/runtime/park.hpp index 504cb1a8524..27d97bccd75 100644 --- a/hotspot/src/share/vm/runtime/park.hpp +++ b/hotspot/src/share/vm/runtime/park.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -121,22 +121,13 @@ class ParkEvent : public os::PlatformEvent { // Current association Thread * AssociatedWith ; - intptr_t RawThreadIdentity ; // LWPID etc - volatile int Incarnation ; - - // diagnostic : keep track of last thread to wake this thread. - // this is useful for construction of dependency graphs. - void * LastWaker ; public: // MCS-CLH list linkage and Native Mutex/Monitor ParkEvent * volatile ListNext ; - ParkEvent * volatile ListPrev ; volatile intptr_t OnList ; volatile int TState ; volatile int Notified ; // for native monitor construct - volatile int IsWaiting ; // Enqueued on WaitSet - private: static ParkEvent * volatile FreeList ; @@ -155,11 +146,9 @@ class ParkEvent : public os::PlatformEvent { AssociatedWith = NULL ; FreeNext = NULL ; ListNext = NULL ; - ListPrev = NULL ; OnList = 0 ; TState = 0 ; Notified = 0 ; - IsWaiting = 0 ; } // We use placement-new to force ParkEvent instances to be diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 7e3c14b56a6..45746d67c7c 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -330,7 +330,7 @@ arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) { return TypeArrayKlass::cast(tak)->allocate(length, THREAD); } else { Klass* k = java_lang_Class::as_Klass(element_mirror); - if (k->oop_is_array() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) { + if (k->is_array_klass() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) { THROW_0(vmSymbols::java_lang_IllegalArgumentException()); } return oopFactory::new_objArray(k, length, THREAD); @@ -366,7 +366,7 @@ arrayOop Reflection::reflect_new_multi_array(oop element_mirror, typeArrayOop di klass = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL); } else { klass = java_lang_Class::as_Klass(element_mirror); - if (klass->oop_is_array()) { + if (klass->is_array_klass()) { int k_dim = ArrayKlass::cast(klass)->dimension(); if (k_dim + len > MAX_DIM) { THROW_0(vmSymbols::java_lang_IllegalArgumentException()); @@ -387,7 +387,7 @@ oop Reflection::array_component_type(oop mirror, TRAPS) { } Klass* klass = java_lang_Class::as_Klass(mirror); - if (!klass->oop_is_array()) { + if (!klass->is_array_klass()) { return NULL; } @@ -395,14 +395,14 @@ oop Reflection::array_component_type(oop mirror, TRAPS) { #ifdef ASSERT oop result2 = NULL; if (ArrayKlass::cast(klass)->dimension() == 1) { - if (klass->oop_is_typeArray()) { + if (klass->is_typeArray_klass()) { result2 = basic_type_arrayklass_to_mirror(klass, CHECK_NULL); } else { result2 = ObjArrayKlass::cast(klass)->element_klass()->java_mirror(); } } else { Klass* lower_dim = ArrayKlass::cast(klass)->lower_dimension(); - assert(lower_dim->oop_is_array(), "just checking"); + assert(lower_dim->is_array_klass(), "just checking"); result2 = lower_dim->java_mirror(); } assert(result == result2, "results must be consistent"); @@ -495,7 +495,7 @@ bool Reflection::verify_field_access(Klass* current_class, } Klass* host_class = current_class; - while (host_class->oop_is_instance() && + while (host_class->is_instance_klass() && InstanceKlass::cast(host_class)->is_anonymous()) { Klass* next_host_class = InstanceKlass::cast(host_class)->host_klass(); if (next_host_class == NULL) break; @@ -612,7 +612,7 @@ oop get_mirror_from_signature(methodHandle method, SignatureStream* ss, TRAPS) { } -objArrayHandle Reflection::get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS) { +objArrayHandle Reflection::get_parameter_types(const methodHandle& method, int parameter_count, oop* return_type, TRAPS) { // Allocate array holding parameter types (java.lang.Class instances) objArrayOop m = oopFactory::new_objArray(SystemDictionary::Class_klass(), parameter_count, CHECK_(objArrayHandle())); objArrayHandle mirrors (THREAD, m); @@ -635,7 +635,7 @@ objArrayHandle Reflection::get_parameter_types(methodHandle method, int paramete return mirrors; } -objArrayHandle Reflection::get_exception_types(methodHandle method, TRAPS) { +objArrayHandle Reflection::get_exception_types(const methodHandle& method, TRAPS) { return method->resolved_checked_exceptions(THREAD); } @@ -647,11 +647,9 @@ Handle Reflection::new_type(Symbol* signature, KlassHandle k, TRAPS) { return Handle(THREAD, Universe::java_mirror(type)); } - oop loader = InstanceKlass::cast(k())->class_loader(); - oop protection_domain = k()->protection_domain(); Klass* result = SystemDictionary::resolve_or_fail(signature, - Handle(THREAD, loader), - Handle(THREAD, protection_domain), + Handle(THREAD, k->class_loader()), + Handle(THREAD, k->protection_domain()), true, CHECK_(Handle())); if (TraceClassResolution) { @@ -663,7 +661,7 @@ Handle Reflection::new_type(Symbol* signature, KlassHandle k, TRAPS) { } -oop Reflection::new_method(methodHandle method, bool for_constant_pool_access, TRAPS) { +oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_access, TRAPS) { // Allow sun.reflect.ConstantPool to refer to methods as java.lang.reflect.Methods. assert(!method()->is_initializer() || (for_constant_pool_access && method()->is_static()), @@ -726,7 +724,7 @@ oop Reflection::new_method(methodHandle method, bool for_constant_pool_access, T } -oop Reflection::new_constructor(methodHandle method, TRAPS) { +oop Reflection::new_constructor(const methodHandle& method, TRAPS) { assert(method()->is_initializer(), "should call new_method instead"); instanceKlassHandle holder (THREAD, method->method_holder()); @@ -824,7 +822,7 @@ oop Reflection::new_parameter(Handle method, int index, Symbol* sym, } -methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method, +methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, const methodHandle& method, KlassHandle recv_klass, Handle receiver, TRAPS) { assert(!method.is_null() , "method should not be null"); @@ -839,7 +837,7 @@ methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, metho } -oop Reflection::invoke(instanceKlassHandle klass, methodHandle reflected_method, +oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_method, Handle receiver, bool override, objArrayHandle ptypes, BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS) { ResourceMark rm(THREAD); diff --git a/hotspot/src/share/vm/runtime/reflection.hpp b/hotspot/src/share/vm/runtime/reflection.hpp index 593ff7ecc49..c73d0b9dfb3 100644 --- a/hotspot/src/share/vm/runtime/reflection.hpp +++ b/hotspot/src/share/vm/runtime/reflection.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -48,8 +48,8 @@ class Reflection: public AllStatic { static Klass* basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS); static oop basic_type_arrayklass_to_mirror(Klass* basic_type_arrayklass, TRAPS); - static objArrayHandle get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS); - static objArrayHandle get_exception_types(methodHandle method, TRAPS); + static objArrayHandle get_parameter_types(const methodHandle& method, int parameter_count, oop* return_type, TRAPS); + static objArrayHandle get_exception_types(const methodHandle& method, TRAPS); // Creating new java.lang.reflect.xxx wrappers static Handle new_type(Symbol* signature, KlassHandle k, TRAPS); @@ -110,9 +110,9 @@ class Reflection: public AllStatic { // // Create a java.lang.reflect.Method object based on a method - static oop new_method(methodHandle method, bool for_constant_pool_access, TRAPS); + static oop new_method(const methodHandle& method, bool for_constant_pool_access, TRAPS); // Create a java.lang.reflect.Constructor object based on a method - static oop new_constructor(methodHandle method, TRAPS); + static oop new_constructor(const methodHandle& method, TRAPS); // Create a java.lang.reflect.Field object based on a field descriptor static oop new_field(fieldDescriptor* fd, TRAPS); // Create a java.lang.reflect.Parameter object based on a @@ -122,9 +122,16 @@ class Reflection: public AllStatic { private: // method resolution for invoke - static methodHandle resolve_interface_call(instanceKlassHandle klass, methodHandle method, KlassHandle recv_klass, Handle receiver, TRAPS); + static methodHandle resolve_interface_call(instanceKlassHandle klass, const methodHandle& method, KlassHandle recv_klass, Handle receiver, TRAPS); // Method call (shared by invoke_method and invoke_constructor) - static oop invoke(instanceKlassHandle klass, methodHandle method, Handle receiver, bool override, objArrayHandle ptypes, BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS); + static oop invoke(instanceKlassHandle klass, + const methodHandle& method, + Handle receiver, + bool override, + objArrayHandle ptypes, + BasicType rtype, + objArrayHandle args, + bool is_method_invoke, TRAPS); // Narrowing of basic types. Used to create correct jvalues for // boolean, byte, char and short return return values from interpreter diff --git a/hotspot/src/share/vm/runtime/relocator.cpp b/hotspot/src/share/vm/runtime/relocator.cpp index 73b1ce3eed4..e6ad4d1bfc7 100644 --- a/hotspot/src/share/vm/runtime/relocator.cpp +++ b/hotspot/src/share/vm/runtime/relocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,7 +125,7 @@ class ChangeSwitchPad : public ChangeItem { //----------------------------------------------------------------------------------------------------------- // Relocator code -Relocator::Relocator(methodHandle m, RelocatorListener* listener) { +Relocator::Relocator(const methodHandle& m, RelocatorListener* listener) { set_method(m); set_code_length(method()->code_size()); set_code_array(NULL); diff --git a/hotspot/src/share/vm/runtime/relocator.hpp b/hotspot/src/share/vm/runtime/relocator.hpp index 6ea9ab4c819..3b5e5f70d5d 100644 --- a/hotspot/src/share/vm/runtime/relocator.hpp +++ b/hotspot/src/share/vm/runtime/relocator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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,7 +44,7 @@ class RelocatorListener : public StackObj { class Relocator : public ResourceObj { public: - Relocator(methodHandle method, RelocatorListener* listener); + Relocator(const methodHandle& method, RelocatorListener* listener); methodHandle insert_space_at(int bci, int space, u_char inst_buffer[], TRAPS); // Callbacks from ChangeItem's @@ -81,7 +81,7 @@ class Relocator : public ResourceObj { void set_compressed_line_number_table_size(int size) { _compressed_line_number_table_size = size; } methodHandle method() const { return _method; } - void set_method(methodHandle method) { _method = method; } + void set_method(const methodHandle& method) { _method = method; } // This will return a raw bytecode, which is possibly rewritten. Bytecodes::Code code_at(int bci) const { return (Bytecodes::Code) code_array()[bci]; } diff --git a/hotspot/src/share/vm/runtime/safepoint.cpp b/hotspot/src/share/vm/runtime/safepoint.cpp index 37d23b4c97c..7fa44f79c67 100644 --- a/hotspot/src/share/vm/runtime/safepoint.cpp +++ b/hotspot/src/share/vm/runtime/safepoint.cpp @@ -33,6 +33,7 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcLocker.inline.hpp" #include "interpreter/interpreter.hpp" +#include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" #include "oops/oop.inline.hpp" @@ -104,9 +105,7 @@ void SafepointSynchronize::begin() { int nof_threads = Threads::number_of_threads(); - if (TraceSafepoint) { - tty->print_cr("Safepoint synchronization initiated. (%d)", nof_threads); - } + log_debug(safepoint)("Safepoint synchronization initiated. (%d)", nof_threads); RuntimeService::record_safepoint_begin(); @@ -122,7 +121,7 @@ void SafepointSynchronize::begin() { // Save the starting time, so that it can be compared to see if this has taken // too long to complete. - jlong safepoint_limit_time; + jlong safepoint_limit_time = 0; timeout_error_printed = false; // PrintSafepointStatisticsTimeout can be specified separately. When @@ -219,7 +218,10 @@ void SafepointSynchronize::begin() { // steps = MIN(steps, 2000-100) // if (iterations != 0) steps -= NNN } - if (TraceSafepoint && Verbose) cur_state->print(); + if (log_is_enabled(Trace, safepoint)) { + ResourceMark rm; + cur_state->print_on(LogHandle(safepoint)::debug_stream()); + } } } @@ -316,7 +318,7 @@ void SafepointSynchronize::begin() { // wait until all threads are stopped while (_waiting_to_block > 0) { - if (TraceSafepoint) tty->print_cr("Waiting for %d thread(s) to block", _waiting_to_block); + log_debug(safepoint)("Waiting for %d thread(s) to block", _waiting_to_block); if (!SafepointTimeout || timeout_error_printed) { Safepoint_lock->wait(true); // true, means with no safepoint checks } else { @@ -362,9 +364,10 @@ void SafepointSynchronize::begin() { // Update the count of active JNI critical regions GC_locker::set_jni_lock_count(_current_jni_active_count); - if (TraceSafepoint) { + if (log_is_enabled(Debug, safepoint)) { VM_Operation *op = VMThread::vm_operation(); - tty->print_cr("Entering safepoint region: %s", (op != NULL) ? op->name() : "no vm operation"); + log_debug(safepoint)("Entering safepoint region: %s", + (op != NULL) ? op->name() : "no vm operation"); } RuntimeService::record_safepoint_synchronized(); @@ -428,9 +431,7 @@ void SafepointSynchronize::end() { _state = _not_synchronized; OrderAccess::fence(); - if (TraceSafepoint) { - tty->print_cr("Leaving safepoint region"); - } + log_debug(safepoint)("Leaving safepoint region"); // Start suspended threads for(JavaThread *current = Threads::first(); current; current = current->next()) { @@ -901,7 +902,7 @@ void ThreadSafepointState::restart() { void ThreadSafepointState::print_on(outputStream *st) const { - const char *s; + const char *s = NULL; switch(_type) { case _running : s = "_running"; break; @@ -919,7 +920,6 @@ void ThreadSafepointState::print_on(outputStream *st) const { _thread->print_thread_state_on(st); } - // --------------------------------------------------------------------------------------------------------------------- // Block the thread at the safepoint poll or poll return. diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 231be768edf..2a78970f4b8 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -37,6 +37,7 @@ #include "gc/shared/gcLocker.inline.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" +#include "logging/log.hpp" #include "memory/universe.inline.hpp" #include "oops/oop.inline.hpp" #include "prims/forte.hpp" @@ -556,17 +557,10 @@ address SharedRuntime::get_poll_stub(address pc) { "polling page safepoint stub not created yet"); stub = SharedRuntime::polling_page_safepoint_handler_blob()->entry_point(); } -#ifndef PRODUCT - if (TraceSafepoint) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), - "... found polling page %s exception at pc = " - INTPTR_FORMAT ", stub =" INTPTR_FORMAT, - at_poll_return ? "return" : "loop", - (intptr_t)pc, (intptr_t)stub); - tty->print_raw_cr(buf); - } -#endif // PRODUCT + log_debug(safepoint)("... found polling page %s exception at pc = " + INTPTR_FORMAT ", stub =" INTPTR_FORMAT, + at_poll_return ? "return" : "loop", + (intptr_t)pc, (intptr_t)stub); return stub; } @@ -1142,7 +1136,7 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, callee->is_method_handle_intrinsic() || callee->is_compiled_lambda_form(), "actual receiver must be subclass of static receiver klass"); - if (receiver_klass->oop_is_instance()) { + if (receiver_klass->is_instance_klass()) { if (InstanceKlass::cast(receiver_klass())->is_not_initialized()) { tty->print_cr("ERROR: Klass not yet initialized!!"); receiver_klass()->print(); @@ -1697,7 +1691,7 @@ methodHandle SharedRuntime::reresolve_call_site(JavaThread *thread, TRAPS) { } #ifdef ASSERT -void SharedRuntime::check_member_name_argument_is_last_argument(methodHandle method, +void SharedRuntime::check_member_name_argument_is_last_argument(const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { ResourceMark rm; @@ -2430,7 +2424,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* finger return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); } -AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { +AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) { // Use customized signature handler. Need to lock around updates to // the AdapterHandlerTable (it is not safe for concurrent readers // and a single writer: this could be fixed if it becomes a @@ -2640,7 +2634,7 @@ bool AdapterHandlerEntry::compare_code(unsigned char* buffer, int length) { * arguments, and transitions to native. On return from the native we transition * back to java blocking if a safepoint is in progress. */ -void AdapterHandlerLibrary::create_native_wrapper(methodHandle method) { +void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) { ResourceMark rm; nmethod* nm = NULL; diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index 65db7ad38e7..1938c9dbb23 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -361,7 +361,7 @@ class SharedRuntime: AllStatic { // return value is the maximum number of VMReg stack slots the convention will use. static int java_calling_convention(const BasicType* sig_bt, VMRegPair* regs, int total_args_passed, int is_outgoing); - static void check_member_name_argument_is_last_argument(methodHandle method, + static void check_member_name_argument_is_last_argument(const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) NOT_DEBUG_RETURN; @@ -472,7 +472,7 @@ class SharedRuntime: AllStatic { // is a JNI critical method, or a compiled method handle adapter, // such as _invokeBasic, _linkToVirtual, etc. static nmethod* generate_native_wrapper(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, int compile_id, BasicType* sig_bt, VMRegPair* regs, @@ -680,8 +680,8 @@ class AdapterHandlerLibrary: public AllStatic { static AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry); - static void create_native_wrapper(methodHandle method); - static AdapterHandlerEntry* get_adapter(methodHandle method); + static void create_native_wrapper(const methodHandle& method); + static AdapterHandlerEntry* get_adapter(const methodHandle& method); static void print_handler(const CodeBlob* b) { print_handler_on(tty, b); } static void print_handler_on(outputStream* st, const CodeBlob* b); diff --git a/hotspot/src/share/vm/runtime/signature.hpp b/hotspot/src/share/vm/runtime/signature.hpp index d1b2e04b1c3..46e36e9f532 100644 --- a/hotspot/src/share/vm/runtime/signature.hpp +++ b/hotspot/src/share/vm/runtime/signature.hpp @@ -242,7 +242,7 @@ class Fingerprinter: public SignatureIterator { void do_void() { ShouldNotReachHere(); } - Fingerprinter(methodHandle method) : SignatureIterator(method->signature()) { + Fingerprinter(const methodHandle& method) : SignatureIterator(method->signature()) { mh = method; _fingerprint = 0; } @@ -320,7 +320,7 @@ class NativeSignatureIterator: public SignatureIterator { virtual void pass_double() { pass_long(); } // may be same as long #endif - NativeSignatureIterator(methodHandle method) : SignatureIterator(method->signature()) { + NativeSignatureIterator(const methodHandle& method) : SignatureIterator(method->signature()) { _method = method; _offset = 0; _jni_offset = 0; diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp index 4b17ca2bc85..db3c1cc1089 100644 --- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, 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 @@ -185,7 +185,7 @@ void SimpleThresholdPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) { } } -nmethod* SimpleThresholdPolicy::event(methodHandle method, methodHandle inlinee, +nmethod* SimpleThresholdPolicy::event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) { if (comp_level == CompLevel_none && JvmtiExport::can_post_interpreter_events() && @@ -222,7 +222,7 @@ nmethod* SimpleThresholdPolicy::event(methodHandle method, methodHandle inlinee, } // Check if the method can be compiled, change level if necessary -void SimpleThresholdPolicy::compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread) { +void SimpleThresholdPolicy::compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) { assert(level <= TieredStopAtLevel, "Invalid compilation level"); if (level == CompLevel_none) { return; @@ -249,7 +249,7 @@ void SimpleThresholdPolicy::compile(methodHandle mh, int bci, CompLevel level, J } // Tell the broker to compile the method -void SimpleThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread) { +void SimpleThresholdPolicy::submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) { int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count(); CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", thread); } @@ -377,7 +377,7 @@ CompLevel SimpleThresholdPolicy::loop_event(Method* method, CompLevel cur_level) // Handle the invocation event. -void SimpleThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh, +void SimpleThresholdPolicy::method_invocation_event(const methodHandle& mh, const methodHandle& imh, CompLevel level, nmethod* nm, JavaThread* thread) { if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) { CompLevel next_level = call_event(mh(), level); @@ -389,7 +389,7 @@ void SimpleThresholdPolicy::method_invocation_event(methodHandle mh, methodHandl // Handle the back branch event. Notice that we can compile the method // with a regular entry from here. -void SimpleThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh, +void SimpleThresholdPolicy::method_back_branch_event(const methodHandle& mh, const methodHandle& imh, int bci, CompLevel level, nmethod* nm, JavaThread* thread) { // If the method is already compiling, quickly bail out. if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) { diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp index 87d009e1360..02a13cadc3c 100644 --- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, 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 @@ -67,9 +67,9 @@ protected: // Print policy-specific information if necessary virtual void print_specific(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level) { } // Check if the method can be compiled, change level if necessary - void compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread); + void compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread); // Submit a given method for compilation - virtual void submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread); + virtual void submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread); // Simple methods are as good being compiled with C1 as C2. // This function tells if it's such a function. inline bool is_trivial(Method* method); @@ -87,9 +87,9 @@ protected: } return CompLevel_none; } - virtual void method_invocation_event(methodHandle method, methodHandle inlinee, + virtual void method_invocation_event(const methodHandle& method, const methodHandle& inlinee, CompLevel level, nmethod* nm, JavaThread* thread); - virtual void method_back_branch_event(methodHandle method, methodHandle inlinee, + virtual void method_back_branch_event(const methodHandle& method, const methodHandle& inlinee, int bci, CompLevel level, nmethod* nm, JavaThread* thread); public: SimpleThresholdPolicy() : _c1_count(0), _c2_count(0) { } @@ -103,7 +103,7 @@ public: virtual void delay_compilation(Method* method) { } virtual void disable_compilation(Method* method) { } virtual void reprofile(ScopeDesc* trap_scope, bool is_osr); - virtual nmethod* event(methodHandle method, methodHandle inlinee, + virtual nmethod* event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread); // Select task is called by CompileBroker. We should return a task or NULL. virtual CompileTask* select_task(CompileQueue* compile_queue); diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp index 05b37c48084..fc7b2d72e84 100644 --- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp @@ -68,6 +68,14 @@ bool SimpleThresholdPolicy::is_trivial(Method* method) { method->is_constant_getter()) { return true; } +#if INCLUDE_JVMCI + if (UseJVMCICompiler) { + if (TieredCompilation && CompileBroker::compiler(CompLevel_full_optimization) != NULL && + CompileBroker::compiler(CompLevel_full_optimization)->is_trivial(method)) { + return true; + } + } +#endif if (method->has_loops() || method->code_size() >= 15) { return false; } diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index fec10fd757b..7046016299f 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -116,7 +116,7 @@ static volatile intptr_t gInflationLocks[NINFLATIONLOCKS]; // global list of blocks of monitors // gBlockList is really PaddedEnd *, but we don't // want to expose the PaddedEnd template more than necessary. -ObjectMonitor * ObjectSynchronizer::gBlockList = NULL; +ObjectMonitor * volatile ObjectSynchronizer::gBlockList = NULL; // global monitor free list ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL; // global monitor in-use list, for moribund threads, @@ -890,21 +890,22 @@ JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) { return NULL; } + // Visitors ... void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) { - PaddedEnd * block = (PaddedEnd *)gBlockList; - ObjectMonitor* mid; - while (block) { + PaddedEnd * block = + (PaddedEnd *)OrderAccess::load_ptr_acquire(&gBlockList); + while (block != NULL) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = _BLOCKSIZE - 1; i > 0; i--) { - mid = (ObjectMonitor *)(block + i); - oop object = (oop) mid->object(); + ObjectMonitor* mid = (ObjectMonitor *)(block + i); + oop object = (oop)mid->object(); if (object != NULL) { closure->do_monitor(mid); } } - block = (PaddedEnd *) block->FreeNext; + block = (PaddedEnd *)block->FreeNext; } } @@ -919,9 +920,9 @@ static inline ObjectMonitor* next(ObjectMonitor* block) { void ObjectSynchronizer::oops_do(OopClosure* f) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - for (PaddedEnd * block = - (PaddedEnd *)gBlockList; block != NULL; - block = (PaddedEnd *)next(block)) { + PaddedEnd * block = + (PaddedEnd *)OrderAccess::load_ptr_acquire(&gBlockList); + for (; block != NULL; block = (PaddedEnd *)next(block)) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = 1; i < _BLOCKSIZE; i++) { ObjectMonitor* mid = (ObjectMonitor *)&block[i]; @@ -1139,7 +1140,9 @@ ObjectMonitor * NOINLINE ObjectSynchronizer::omAlloc(Thread * Self) { // The very first objectMonitor in a block is reserved and dedicated. // It serves as blocklist "next" linkage. temp[0].FreeNext = gBlockList; - gBlockList = temp; + // There are lock-free uses of gBlockList so make sure that + // the previous stores happen before we update gBlockList. + OrderAccess::release_store_ptr(&gBlockList, temp); // Add the new string of objectMonitors to the global free list temp[_BLOCKSIZE - 1].FreeNext = gFreeList; @@ -1621,31 +1624,33 @@ void ObjectSynchronizer::deflate_idle_monitors() { nInuse += gOmInUseCount; } - } else for (PaddedEnd * block = - (PaddedEnd *)gBlockList; block != NULL; - block = (PaddedEnd *)next(block)) { - // Iterate over all extant monitors - Scavenge all idle monitors. - assert(block->object() == CHAINMARKER, "must be a block header"); - nInCirculation += _BLOCKSIZE; - for (int i = 1; i < _BLOCKSIZE; i++) { - ObjectMonitor* mid = (ObjectMonitor*)&block[i]; - oop obj = (oop) mid->object(); + } else { + PaddedEnd * block = + (PaddedEnd *)OrderAccess::load_ptr_acquire(&gBlockList); + for (; block != NULL; block = (PaddedEnd *)next(block)) { + // Iterate over all extant monitors - Scavenge all idle monitors. + assert(block->object() == CHAINMARKER, "must be a block header"); + nInCirculation += _BLOCKSIZE; + for (int i = 1; i < _BLOCKSIZE; i++) { + ObjectMonitor* mid = (ObjectMonitor*)&block[i]; + oop obj = (oop)mid->object(); - if (obj == NULL) { - // The monitor is not associated with an object. - // The monitor should either be a thread-specific private - // free list or the global free list. - // obj == NULL IMPLIES mid->is_busy() == 0 - guarantee(!mid->is_busy(), "invariant"); - continue; - } - deflated = deflate_monitor(mid, obj, &freeHeadp, &freeTailp); + if (obj == NULL) { + // The monitor is not associated with an object. + // The monitor should either be a thread-specific private + // free list or the global free list. + // obj == NULL IMPLIES mid->is_busy() == 0 + guarantee(!mid->is_busy(), "invariant"); + continue; + } + deflated = deflate_monitor(mid, obj, &freeHeadp, &freeTailp); - if (deflated) { - mid->FreeNext = NULL; - nScavenged++; - } else { - nInuse++; + if (deflated) { + mid->FreeNext = NULL; + nScavenged++; + } else { + nInuse++; + } } } } @@ -1789,18 +1794,18 @@ void ObjectSynchronizer::sanity_checks(const bool verbose, // Verify all monitors in the monitor cache, the verification is weak. void ObjectSynchronizer::verify() { - PaddedEnd * block = (PaddedEnd *)gBlockList; - ObjectMonitor* mid; - while (block) { + PaddedEnd * block = + (PaddedEnd *)OrderAccess::load_ptr_acquire(&gBlockList); + while (block != NULL) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = 1; i < _BLOCKSIZE; i++) { - mid = (ObjectMonitor *)(block + i); - oop object = (oop) mid->object(); + ObjectMonitor* mid = (ObjectMonitor *)(block + i); + oop object = (oop)mid->object(); if (object != NULL) { mid->verify(); } } - block = (PaddedEnd *) block->FreeNext; + block = (PaddedEnd *)block->FreeNext; } } @@ -1809,19 +1814,19 @@ void ObjectSynchronizer::verify() { // the list of extant blocks without taking a lock. int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) { - PaddedEnd * block = (PaddedEnd *)gBlockList; - - while (block) { + PaddedEnd * block = + (PaddedEnd *)OrderAccess::load_ptr_acquire(&gBlockList); + while (block != NULL) { assert(block->object() == CHAINMARKER, "must be a block header"); if (monitor > (ObjectMonitor *)&block[0] && monitor < (ObjectMonitor *)&block[_BLOCKSIZE]) { - address mon = (address) monitor; - address blk = (address) block; + address mon = (address)monitor; + address blk = (address)block; size_t diff = mon - blk; - assert((diff % sizeof(PaddedEnd)) == 0, "check"); + assert((diff % sizeof(PaddedEnd)) == 0, "must be aligned"); return 1; } - block = (PaddedEnd *) block->FreeNext; + block = (PaddedEnd *)block->FreeNext; } return 0; } diff --git a/hotspot/src/share/vm/runtime/synchronizer.hpp b/hotspot/src/share/vm/runtime/synchronizer.hpp index b08bd1bad19..0d577bf3303 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.hpp +++ b/hotspot/src/share/vm/runtime/synchronizer.hpp @@ -140,7 +140,7 @@ class ObjectSynchronizer : AllStatic { // global list of blocks of monitors // gBlockList is really PaddedEnd *, but we don't // want to expose the PaddedEnd template more than necessary. - static ObjectMonitor * gBlockList; + static ObjectMonitor * volatile gBlockList; // global monitor free list static ObjectMonitor * volatile gFreeList; // global monitor in-use list, for moribund threads, diff --git a/hotspot/src/share/vm/runtime/task.cpp b/hotspot/src/share/vm/runtime/task.cpp index 6e06efa7282..89dc0ab9aa8 100644 --- a/hotspot/src/share/vm/runtime/task.cpp +++ b/hotspot/src/share/vm/runtime/task.cpp @@ -117,8 +117,9 @@ void PeriodicTask::enroll() { if (_num_tasks == PeriodicTask::max_tasks) { fatal("Overflow in PeriodicTask table"); + } else { + _tasks[_num_tasks++] = this; } - _tasks[_num_tasks++] = this; WatcherThread* thread = WatcherThread::watcher_thread(); if (thread != NULL) { diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 1fa6e2a7325..de7c4139059 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1868,13 +1868,10 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { // Optionally release any monitors for regular JavaThread exits. This // is provided as a work around for any bugs in monitor enter-exit // matching. This can be expensive so it is not enabled by default. - // ObjectMonitor::Knob_ExitRelease is a superset of the - // JNIDetachReleasesMonitors option. // // ensure_join() ignores IllegalThreadStateExceptions, and so does // ObjectSynchronizer::release_monitors_owned_by_thread(). - if ((exit_type == jni_detach && JNIDetachReleasesMonitors) || - ObjectMonitor::Knob_ExitRelease) { + if (exit_type == jni_detach || ObjectMonitor::Knob_ExitRelease) { // Sanity check even though JNI DetachCurrentThread() would have // returned JNI_ERR if there was a Java frame. JavaThread exit // should be done executing Java code by the time we get here. @@ -1941,7 +1938,7 @@ void JavaThread::initialize_queues() { assert(!SafepointSynchronize::is_at_safepoint(), "we should not be at a safepoint"); - ObjPtrQueue& satb_queue = satb_mark_queue(); + SATBMarkQueue& satb_queue = satb_mark_queue(); SATBMarkQueueSet& satb_queue_set = satb_mark_queue_set(); // The SATB queue should have been constructed with its active // field set to false. @@ -2101,7 +2098,7 @@ void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) { frame f = last_frame(); tty->print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", p2i(f.pc()), p2i(f.sp())); } - tty->print_cr(" of type: %s", InstanceKlass::cast(_pending_async_exception->klass())->external_name()); + tty->print_cr(" of type: %s", _pending_async_exception->klass()->external_name()); } _pending_async_exception = NULL; clear_has_async_exception(); @@ -2219,10 +2216,10 @@ void JavaThread::send_thread_stop(oop java_throwable) { if (TraceExceptions) { ResourceMark rm; - tty->print_cr("Pending Async. exception installed of type: %s", InstanceKlass::cast(_pending_async_exception->klass())->external_name()); + tty->print_cr("Pending Async. exception installed of type: %s", _pending_async_exception->klass()->external_name()); } // for AbortVMOnException flag - Exceptions::debug_check_abort(InstanceKlass::cast(_pending_async_exception->klass())->external_name()); + Exceptions::debug_check_abort(_pending_async_exception->klass()->external_name()); } } @@ -2933,12 +2930,8 @@ const char* JavaThread::get_threadgroup_name() const { if (thread_obj != NULL) { oop thread_group = java_lang_Thread::threadGroup(thread_obj); if (thread_group != NULL) { - typeArrayOop name = java_lang_ThreadGroup::name(thread_group); // ThreadGroup.name can be null - if (name != NULL) { - const char* str = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); - return str; - } + return java_lang_ThreadGroup::name(thread_group); } } return NULL; @@ -2952,12 +2945,8 @@ const char* JavaThread::get_parent_name() const { if (thread_group != NULL) { oop parent = java_lang_ThreadGroup::parent(thread_group); if (parent != NULL) { - typeArrayOop name = java_lang_ThreadGroup::name(parent); // ThreadGroup.name can be null - if (name != NULL) { - const char* str = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); - return str; - } + return java_lang_ThreadGroup::name(parent); } } } @@ -3304,6 +3293,9 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { initialize_class(vmSymbols::java_lang_String(), CHECK); + // Inject CompactStrings value after the static initializers for String ran. + java_lang_String::set_compact_strings(CompactStrings); + // Initialize java_lang.System (needed before creating the thread) initialize_class(vmSymbols::java_lang_System(), CHECK); // The VM creates & returns objects of this class. Make sure it's initialized. @@ -3630,6 +3622,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { if (jvmciCompiler != NULL) { JVMCIRuntime::save_compiler(jvmciCompiler); } + JVMCIRuntime::maybe_print_flags(CHECK_JNI_ERR); } #endif // INCLUDE_JVMCI diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 2c0411d8f26..27c81f00346 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -49,7 +49,7 @@ #include "utilities/top.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/dirtyCardQueue.hpp" -#include "gc/g1/satbQueue.hpp" +#include "gc/g1/satbMarkQueue.hpp" #endif // INCLUDE_ALL_GCS #ifdef TARGET_ARCH_zero # include "stack_zero.hpp" @@ -992,7 +992,7 @@ class JavaThread: public Thread { #if INCLUDE_ALL_GCS // Support for G1 barriers - ObjPtrQueue _satb_mark_queue; // Thread-local log for SATB barrier. + SATBMarkQueue _satb_mark_queue; // Thread-local log for SATB barrier. // Set of all such queues. static SATBMarkQueueSet _satb_mark_queue_set; @@ -1727,7 +1727,7 @@ class JavaThread: public Thread { #if INCLUDE_ALL_GCS // SATB marking queue support - ObjPtrQueue& satb_mark_queue() { return _satb_mark_queue; } + SATBMarkQueue& satb_mark_queue() { return _satb_mark_queue; } static SATBMarkQueueSet& satb_mark_queue_set() { return _satb_mark_queue_set; } diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index ee9a24d6900..784c8be3eb7 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -278,6 +278,7 @@ typedef CompactHashtable SymbolCompactHashTable; #define VM_STRUCTS(nonstatic_field, \ static_field, \ + static_ptr_volatile_field, \ unchecked_nonstatic_field, \ volatile_nonstatic_field, \ nonproduct_nonstatic_field, \ @@ -681,42 +682,42 @@ typedef CompactHashtable SymbolCompactHashTable; static_field(SystemDictionary, _shared_dictionary, Dictionary*) \ static_field(SystemDictionary, _system_loader_lock_obj, oop) \ static_field(SystemDictionary, _loader_constraints, LoaderConstraintTable*) \ - static_field(SystemDictionary, WK_KLASS(Object_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(String_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Class_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Cloneable_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(ClassLoader_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Serializable_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(System_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Throwable_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(ThreadDeath_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Error_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Exception_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(RuntimeException_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(ClassNotFoundException_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(NoClassDefFoundError_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(LinkageError_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(ClassCastException_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(ArrayStoreException_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(VirtualMachineError_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(OutOfMemoryError_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(SecureClassLoader_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Reference_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(SoftReference_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(FinalReference_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Cleaner_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Finalizer_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Thread_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(Properties_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(StringBuffer_klass), Klass*) \ - static_field(SystemDictionary, WK_KLASS(MethodHandle_klass), Klass*) \ - static_field(SystemDictionary, _box_klasses[0], Klass*) \ + static_field(SystemDictionary, WK_KLASS(Object_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(String_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Class_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Cloneable_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(ClassLoader_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Serializable_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(System_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Throwable_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(ThreadDeath_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Error_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Exception_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(RuntimeException_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(ClassNotFoundException_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(NoClassDefFoundError_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(LinkageError_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(ClassCastException_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(ArrayStoreException_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(VirtualMachineError_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(OutOfMemoryError_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(SecureClassLoader_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Reference_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(SoftReference_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(WeakReference_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(FinalReference_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Cleaner_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Finalizer_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Thread_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(Properties_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(StringBuffer_klass), InstanceKlass*) \ + static_field(SystemDictionary, WK_KLASS(MethodHandle_klass), InstanceKlass*) \ + static_field(SystemDictionary, _box_klasses[0], InstanceKlass*) \ static_field(SystemDictionary, _java_system_loader, oop) \ \ /*************/ \ @@ -1024,7 +1025,7 @@ typedef CompactHashtable SymbolCompactHashTable; nonstatic_field(JavaThread, _stack_size, size_t) \ nonstatic_field(JavaThread, _vframe_array_head, vframeArray*) \ nonstatic_field(JavaThread, _vframe_array_last, vframeArray*) \ - nonstatic_field(JavaThread, _satb_mark_queue, ObjPtrQueue) \ + nonstatic_field(JavaThread, _satb_mark_queue, SATBMarkQueue) \ nonstatic_field(JavaThread, _dirty_card_queue, DirtyCardQueue) \ nonstatic_field(Thread, _resource_area, ResourceArea*) \ nonstatic_field(CompilerThread, _env, ciEnv*) \ @@ -1178,7 +1179,7 @@ typedef CompactHashtable SymbolCompactHashTable; volatile_nonstatic_field(BasicLock, _displaced_header, markOop) \ nonstatic_field(BasicObjectLock, _lock, BasicLock) \ nonstatic_field(BasicObjectLock, _obj, oop) \ - static_field(ObjectSynchronizer, gBlockList, ObjectMonitor*) \ + static_ptr_volatile_field(ObjectSynchronizer, gBlockList, ObjectMonitor*) \ \ /*********************/ \ /* Matcher (C2 only) */ \ @@ -1616,7 +1617,7 @@ typedef CompactHashtable SymbolCompactHashTable; declare_toplevel_type(MemRegion) \ declare_toplevel_type(ThreadLocalAllocBuffer) \ declare_toplevel_type(VirtualSpace) \ - declare_toplevel_type(ObjPtrQueue) \ + declare_toplevel_type(SATBMarkQueue) \ declare_toplevel_type(DirtyCardQueue) \ \ /* Pointers to Garbage Collection types */ \ @@ -2897,6 +2898,11 @@ typedef CompactHashtable SymbolCompactHashTable; #define GENERATE_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, &typeName::fieldName }, +// This macro generates a VMStructEntry line for a static pointer volatile field, +// e.g.: "static ObjectMonitor * volatile gBlockList;" +#define GENERATE_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type) \ + { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, (void *)&typeName::fieldName }, + // This macro generates a VMStructEntry line for an unchecked // nonstatic field, in which the size of the type is also specified. // The type string is given as NULL, indicating an "opaque" type. @@ -2922,10 +2928,15 @@ typedef CompactHashtable SymbolCompactHashTable; #define CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ {typedef type dummyvtype; typeName *dummyObj = NULL; volatile dummyvtype* dummy = &dummyObj->fieldName; } -// This macro checks the type of a VMStructEntry by comparing pointer types +// This macro checks the type of a static VMStructEntry by comparing pointer types #define CHECK_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ {type* dummy = &typeName::fieldName; } +// This macro checks the type of a static pointer volatile VMStructEntry by comparing pointer types, +// e.g.: "static ObjectMonitor * volatile gBlockList;" +#define CHECK_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type) \ + {type volatile * dummy = &typeName::fieldName; } + // This macro ensures the type of a field and its containing type are // present in the type table. The assertion string is shorter than // preferable because (incredibly) of a bug in Solstice NFS client @@ -3136,6 +3147,7 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = { VM_STRUCTS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY, + GENERATE_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY, GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, @@ -3365,6 +3377,7 @@ void VMStructs::init() { VM_STRUCTS(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY, + CHECK_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY, CHECK_NO_OP, CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, @@ -3486,8 +3499,10 @@ VMStructs::init() { CHECK_NO_OP, CHECK_NO_OP, CHECK_NO_OP, + CHECK_NO_OP, CHECK_NO_OP)); debug_only(VM_STRUCTS(CHECK_NO_OP, + ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT, CHECK_NO_OP, ENSURE_FIELD_TYPE_PRESENT, diff --git a/hotspot/src/share/vm/services/attachListener.hpp b/hotspot/src/share/vm/services/attachListener.hpp index 5204c4c625a..8c5be4a463b 100644 --- a/hotspot/src/share/vm/services/attachListener.hpp +++ b/hotspot/src/share/vm/services/attachListener.hpp @@ -29,6 +29,7 @@ #include "utilities/debug.hpp" #include "utilities/ostream.hpp" #include "utilities/macros.hpp" +#include "utilities/globalDefinitions.hpp" // The AttachListener thread services a queue of operations that are enqueued // by client tools. Each operation is identified by a name and has up to 3 @@ -121,8 +122,9 @@ class AttachOperation: public CHeapObj { // set the operation name void set_name(char* name) { - assert(strlen(name) <= name_length_max, "exceeds maximum name length"); - strcpy(_name, name); + size_t len = strlen(name); + assert(len <= name_length_max, "exceeds maximum name length"); + memcpy(_name, name, MIN2(len + 1, (size_t)name_length_max)); } // get an argument value @@ -137,8 +139,9 @@ class AttachOperation: public CHeapObj { if (arg == NULL) { _arg[i][0] = '\0'; } else { - assert(strlen(arg) <= arg_length_max, "exceeds maximum argument length"); - strcpy(_arg[i], arg); + size_t len = strlen(arg); + assert(len <= arg_length_max, "exceeds maximum argument length"); + memcpy(_arg[i], arg, MIN2(len + 1, (size_t)arg_length_max)); } } diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index 1525188d1a7..24c76e5d172 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -164,7 +164,7 @@ size_t ClassLoadingService::compute_class_size(InstanceKlass* k) { class_size += k->size(); - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { class_size += k->methods()->size(); // FIXME: Need to count the contents of methods class_size += k->constants()->size(); diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index 937d909b6f4..96ea8d7a744 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -722,7 +722,7 @@ void DumperSupport::dump_field_value(DumpWriter* writer, char type, address addr o = oopDesc::load_decode_heap_oop((oop*)addr); } - // reflection and sun.misc.Unsafe classes may have a reference to a + // reflection and Unsafe classes may have a reference to a // Klass* so filter it out. assert(o->is_oop_or_null(), "Expected an oop or NULL at " PTR_FORMAT, p2i(o)); writer->write_objectID(o); @@ -895,12 +895,12 @@ void DumperSupport::dump_instance(DumpWriter* writer, oop o) { // creates HPROF_GC_CLASS_DUMP record for the given class and each of // its array classes void DumperSupport::dump_class_and_array_classes(DumpWriter* writer, Klass* k) { - Klass* klass = k; - assert(klass->oop_is_instance(), "not an InstanceKlass"); - InstanceKlass* ik = (InstanceKlass*)klass; + InstanceKlass* ik = InstanceKlass::cast(k); - // Ignore the class if it hasn't been initialized yet - if (!ik->is_linked()) { + // We can safepoint and do a heap dump at a point where we have a Klass, + // but no java mirror class has been setup for it. So we need to check + // that the class is at least loaded, to avoid crash from a null mirror. + if (!ik->is_loaded()) { return; } @@ -939,10 +939,10 @@ void DumperSupport::dump_class_and_array_classes(DumpWriter* writer, Klass* k) { dump_instance_field_descriptors(writer, k); // array classes - k = klass->array_klass_or_null(); + k = k->array_klass_or_null(); while (k != NULL) { Klass* klass = k; - assert(klass->oop_is_objArray(), "not an ObjArrayKlass"); + assert(klass->is_objArray_klass(), "not an ObjArrayKlass"); writer->write_u1(HPROF_GC_CLASS_DUMP); writer->write_classID(klass); @@ -1126,7 +1126,7 @@ void DumperSupport::dump_stack_frame(DumpWriter* writer, writer->write_symbolID(m->name()); // method's name writer->write_symbolID(m->signature()); // method's signature - assert(m->method_holder()->oop_is_instance(), "not InstanceKlass"); + assert(m->method_holder()->is_instance_klass(), "not InstanceKlass"); writer->write_symbolID(m->method_holder()->source_file_name()); // source file name writer->write_u4(class_serial_num); // class serial number writer->write_u4((u4) line_number); // line number @@ -1248,7 +1248,7 @@ class StickyClassDumper : public KlassClosure { _writer = writer; } void do_klass(Klass* k) { - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k); writer()->write_u1(HPROF_GC_ROOT_STICKY_CLASS); writer()->write_classID(ik); @@ -1396,7 +1396,7 @@ class VM_HeapDumper : public VM_GC_Operation { if (oome) { assert(!Thread::current()->is_VM_thread(), "Dump from OutOfMemoryError cannot be called by the VMThread"); // get OutOfMemoryError zero-parameter constructor - InstanceKlass* oome_ik = InstanceKlass::cast(SystemDictionary::OutOfMemoryError_klass()); + InstanceKlass* oome_ik = SystemDictionary::OutOfMemoryError_klass(); _oome_constructor = oome_ik->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature()); // get thread throwing OOME when generating the heap dump at OOME @@ -1553,7 +1553,7 @@ void VM_HeapDumper::do_load_class(Klass* k) { // writes a HPROF_GC_CLASS_DUMP record for the given class void VM_HeapDumper::do_class_dump(Klass* k) { - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { DumperSupport::dump_class_and_array_classes(writer(), k); } } @@ -1850,7 +1850,6 @@ void VM_HeapDumper::dump_stack_traces() { } // dump the heap to given path. -PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL int HeapDumper::dump(const char* path) { assert(path != NULL && strlen(path) > 0, "path missing"); @@ -1888,13 +1887,8 @@ int HeapDumper::dump(const char* path) { if (print_to_tty()) { timer()->stop(); if (error() == NULL) { - char msg[256]; - sprintf(msg, "Heap dump file created [%s bytes in %3.3f secs]", - JLONG_FORMAT, timer()->seconds()); -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL - tty->print_cr(msg, writer.bytes_written()); -PRAGMA_DIAG_POP + tty->print_cr("Heap dump file created [" JLONG_FORMAT " bytes in %3.3f secs]", + writer.bytes_written(), timer()->seconds()); } else { tty->print_cr("Dump file is incomplete: %s", writer.error()); } @@ -1979,7 +1973,7 @@ void HeapDumper::dump_heap(bool oome) { if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') { // HeapDumpPath= not specified } else { - strncpy(base_path, HeapDumpPath, sizeof(base_path)); + strcpy(base_path, HeapDumpPath); // check if the path is a directory (must exist) DIR* dir = os::opendir(base_path); if (dir == NULL) { diff --git a/hotspot/src/share/vm/services/memoryService.cpp b/hotspot/src/share/vm/services/memoryService.cpp index dddea1589fe..187425ba92b 100644 --- a/hotspot/src/share/vm/services/memoryService.cpp +++ b/hotspot/src/share/vm/services/memoryService.cpp @@ -546,7 +546,7 @@ Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) { CHECK_NH); return obj; } -// + // GC manager type depends on the type of Generation. Depending on the space // availability and vm options the gc uses major gc manager or minor gc // manager or both. The type of gc manager depends on the generation kind. @@ -559,21 +559,23 @@ TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause: #if INCLUDE_ALL_GCS case Generation::ParNew: #endif // INCLUDE_ALL_GCS - _fullGC=false; + _fullGC = false; break; case Generation::MarkSweepCompact: #if INCLUDE_ALL_GCS case Generation::ConcurrentMarkSweep: #endif // INCLUDE_ALL_GCS - _fullGC=true; + _fullGC = true; break; default: + _fullGC = false; assert(false, "Unrecognized gc generation kind."); } // this has to be called in a stop the world pause and represent // an entire gc pause, start to finish: - initialize(_fullGC, cause,true, true, true, true, true, true, true); + initialize(_fullGC, cause, true, true, true, true, true, true, true); } + TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC, GCCause::Cause cause, bool recordGCBeginTime, @@ -583,7 +585,7 @@ TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC, bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection) { - initialize(fullGC, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, + initialize(fullGC, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, countCollection); } diff --git a/hotspot/src/share/vm/services/serviceUtil.hpp b/hotspot/src/share/vm/services/serviceUtil.hpp index 42e03d9df53..fca509770c2 100644 --- a/hotspot/src/share/vm/services/serviceUtil.hpp +++ b/hotspot/src/share/vm/services/serviceUtil.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -57,13 +57,13 @@ class ServiceUtil : public AllStatic { if (k->is_klass()) { // if it's a class for an object, an object array, or // primitive (type) array then it's visible. - if (k->oop_is_instance()) { + if (k->is_instance_klass()) { return true; } - if (k->oop_is_objArray()) { + if (k->is_objArray_klass()) { return true; } - if (k->oop_is_typeArray()) { + if (k->is_typeArray_klass()) { return true; } } diff --git a/hotspot/src/share/vm/services/threadService.cpp b/hotspot/src/share/vm/services/threadService.cpp index 0551deff70c..d0598e46195 100644 --- a/hotspot/src/share/vm/services/threadService.cpp +++ b/hotspot/src/share/vm/services/threadService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -505,8 +505,7 @@ void StackFrameInfo::print_on(outputStream* st) const { int len = (_locked_monitors != NULL ? _locked_monitors->length() : 0); for (int i = 0; i < len; i++) { oop o = _locked_monitors->at(i); - InstanceKlass* ik = InstanceKlass::cast(o->klass()); - st->print_cr("\t- locked <" INTPTR_FORMAT "> (a %s)", p2i(o), ik->external_name()); + st->print_cr("\t- locked <" INTPTR_FORMAT "> (a %s)", p2i(o), o->klass()->external_name()); } } @@ -729,8 +728,7 @@ void ConcurrentLocksDump::print_locks_on(JavaThread* t, outputStream* st) { for (int i = 0; i < locks->length(); i++) { instanceOop obj = locks->at(i); - InstanceKlass* ik = InstanceKlass::cast(obj->klass()); - st->print_cr("\t- <" INTPTR_FORMAT "> (a %s)", p2i(obj), ik->external_name()); + st->print_cr("\t- <" INTPTR_FORMAT "> (a %s)", p2i(obj), obj->klass()->external_name()); } st->cr(); } @@ -887,7 +885,7 @@ void DeadlockCycle::print_on(outputStream* st) const { oop obj = (oop)waitingToLockMonitor->object(); if (obj != NULL) { st->print(" (object " INTPTR_FORMAT ", a %s)", p2i(obj), - (InstanceKlass::cast(obj->klass()))->external_name()); + obj->klass()->external_name()); if (!currentThread->current_pending_monitor_is_from_java()) { owner_desc = "\n in JNI, which is held by"; @@ -911,7 +909,7 @@ void DeadlockCycle::print_on(outputStream* st) const { } else { st->print(" waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)", p2i(waitingToLockBlocker), - (InstanceKlass::cast(waitingToLockBlocker->klass()))->external_name()); + waitingToLockBlocker->klass()->external_name()); assert(waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass()), "Must be an AbstractOwnableSynchronizer"); oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker); diff --git a/hotspot/src/share/vm/services/threadService.hpp b/hotspot/src/share/vm/services/threadService.hpp index f5c5121d80c..46bc012f73e 100644 --- a/hotspot/src/share/vm/services/threadService.hpp +++ b/hotspot/src/share/vm/services/threadService.hpp @@ -425,12 +425,12 @@ class JavaThreadStatusChanger : public StackObj { } JavaThreadStatusChanger(JavaThread* java_thread, - java_lang_Thread::ThreadStatus state) { + java_lang_Thread::ThreadStatus state) : _old_state(java_lang_Thread::NEW) { save_old_state(java_thread); set_thread_status(state); } - JavaThreadStatusChanger(JavaThread* java_thread) { + JavaThreadStatusChanger(JavaThread* java_thread) : _old_state(java_lang_Thread::NEW) { save_old_state(java_thread); } @@ -527,7 +527,7 @@ class JavaThreadBlockedOnMonitorEnterState : public JavaThreadStatusChanger { // Current thread is the notifying thread which holds the monitor. static bool wait_reenter_begin(JavaThread *java_thread, ObjectMonitor *obj_m) { assert((java_thread != NULL), "Java thread should not be null here"); - bool active = false; + bool active = false; if (is_alive(java_thread) && ServiceUtil::visible_oop((oop)obj_m->object())) { active = contended_enter_begin(java_thread); } @@ -542,7 +542,7 @@ class JavaThreadBlockedOnMonitorEnterState : public JavaThreadStatusChanger { } JavaThreadBlockedOnMonitorEnterState(JavaThread *java_thread, ObjectMonitor *obj_m) : - JavaThreadStatusChanger(java_thread) { + _stat(NULL), _active(false), JavaThreadStatusChanger(java_thread) { assert((java_thread != NULL), "Java thread should not be null here"); // Change thread status and collect contended enter stats for monitor contended // enter done for external java world objects and it is contended. All other cases diff --git a/hotspot/src/share/vm/services/writeableFlags.cpp b/hotspot/src/share/vm/services/writeableFlags.cpp index 4dda4b3e981..3541fddaece 100644 --- a/hotspot/src/share/vm/services/writeableFlags.cpp +++ b/hotspot/src/share/vm/services/writeableFlags.cpp @@ -57,7 +57,6 @@ static void print_flag_error_message_bounds(const char* name, char* buffer) { } } -PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL static void print_flag_error_message_if_needed(Flag::Error error, const char* name, FormatBuffer<80>& err_msg) { if (error == Flag::SUCCESS) { return; diff --git a/hotspot/src/share/vm/shark/sharkCompiler.cpp b/hotspot/src/share/vm/shark/sharkCompiler.cpp index e3188ce8fa9..78c9335d228 100644 --- a/hotspot/src/share/vm/shark/sharkCompiler.cpp +++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -223,7 +223,7 @@ void SharkCompiler::compile_method(ciEnv* env, } nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm, - methodHandle target, + const methodHandle& target, int compile_id, BasicType* arg_types, BasicType return_type) { diff --git a/hotspot/src/share/vm/shark/sharkCompiler.hpp b/hotspot/src/share/vm/shark/sharkCompiler.hpp index 0013e376c5e..7c4179371d1 100644 --- a/hotspot/src/share/vm/shark/sharkCompiler.hpp +++ b/hotspot/src/share/vm/shark/sharkCompiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -47,7 +47,7 @@ class SharkCompiler : public AbstractCompiler { // Missing feature tests bool supports_native() { return true; } bool supports_osr() { return true; } - bool can_compile_method(methodHandle method) { + bool can_compile_method(const methodHandle& method) { return ! (method->is_method_handle_intrinsic() || method->is_compiled_lambda_form()); } @@ -62,7 +62,7 @@ class SharkCompiler : public AbstractCompiler { // Generate a wrapper for a native (JNI) method nmethod* generate_native_wrapper(MacroAssembler* masm, - methodHandle target, + const methodHandle& target, int compile_id, BasicType* arg_types, BasicType return_type); diff --git a/hotspot/src/share/vm/shark/sharkIntrinsics.cpp b/hotspot/src/share/vm/shark/sharkIntrinsics.cpp index 9ad91c96d79..51b813f4b8d 100644 --- a/hotspot/src/share/vm/shark/sharkIntrinsics.cpp +++ b/hotspot/src/share/vm/shark/sharkIntrinsics.cpp @@ -65,7 +65,7 @@ bool SharkIntrinsics::is_intrinsic(ciMethod *target) { case vmIntrinsics::_currentThread: return true; - // sun.misc.Unsafe + // Unsafe case vmIntrinsics::_compareAndSwapInt: return true; @@ -139,7 +139,7 @@ void SharkIntrinsics::do_intrinsic() { do_Thread_currentThread(); break; - // sun.misc.Unsafe + // Unsafe case vmIntrinsics::_compareAndSwapInt: do_Unsafe_compareAndSwapInt(); break; diff --git a/hotspot/src/share/vm/utilities/exceptions.cpp b/hotspot/src/share/vm/utilities/exceptions.cpp index 0d5a12debb7..ef14a9ff121 100644 --- a/hotspot/src/share/vm/utilities/exceptions.cpp +++ b/hotspot/src/share/vm/utilities/exceptions.cpp @@ -222,7 +222,7 @@ void Exceptions::_throw_cause(Thread* thread, const char* file, int line, Symbol } -void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line, methodHandle method) { +void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line, const methodHandle& method) { Handle exception; if (!THREAD->has_pending_exception()) { Klass* k = SystemDictionary::StackOverflowError_klass(); @@ -502,5 +502,5 @@ void Exceptions::debug_check_abort_helper(Handle exception, const char* message) message = java_lang_String::as_utf8_string(msg); } } - debug_check_abort(InstanceKlass::cast(exception()->klass())->external_name(), message); + debug_check_abort(exception()->klass()->external_name(), message); } diff --git a/hotspot/src/share/vm/utilities/exceptions.hpp b/hotspot/src/share/vm/utilities/exceptions.hpp index 6575090f1f4..02d9110ef74 100644 --- a/hotspot/src/share/vm/utilities/exceptions.hpp +++ b/hotspot/src/share/vm/utilities/exceptions.hpp @@ -163,7 +163,7 @@ class Exceptions { const char* message, ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8); - static void throw_stack_overflow_exception(Thread* thread, const char* file, int line, methodHandle method); + static void throw_stack_overflow_exception(Thread* thread, const char* file, int line, const methodHandle& method); // Exception counting for error files of interesting exceptions that may have // caused a problem for the jvm diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp index 5324d987f09..836e25b4f89 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp @@ -287,8 +287,6 @@ inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); } // Tested to work with clang version 3.1 and better. #define PRAGMA_DIAG_PUSH _Pragma("GCC diagnostic push") #define PRAGMA_DIAG_POP _Pragma("GCC diagnostic pop") -#define PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL -#define PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL PRAGMA_FORMAT_NONLITERAL_IGNORED // Hack to deal with gcc yammering about non-security format stuff #else @@ -297,8 +295,6 @@ inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); } // versions of the macro-pragma to obtain better checking with newer compilers. #define PRAGMA_DIAG_PUSH #define PRAGMA_DIAG_POP -#define PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL PRAGMA_FORMAT_NONLITERAL_IGNORED -#define PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL #endif #if (__GNUC__ == 2) && (__GNUC_MINOR__ < 95) diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp index 6e8c0e17f7a..f4a87437199 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp @@ -171,9 +171,11 @@ const jlong max_jlong = CONST64(0x7fffffffffffffff); #define strdup _strdup #endif -// Visual Studio 2013 introduced strtoull(); before, one has to use _strtoui64() instead. #if _MSC_VER < 1800 +// Visual Studio 2013 introduced strtoull(); before, one has to use _strtoui64() instead. #define strtoull _strtoui64 +// Fixes some wrong warnings about 'this' : used in base member initializer list +#pragma warning( disable : 4355 ) #endif diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index f0e127f4307..0e9584e46b0 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -1449,6 +1449,6 @@ void logStream::write(const char* s, size_t len) { _current_line.reset(); } else { _current_line.write(s, len); - update_position(s, len); } + update_position(s, len); } diff --git a/hotspot/src/share/vm/utilities/resourceHash.cpp b/hotspot/src/share/vm/utilities/resourceHash.cpp new file mode 100644 index 00000000000..36088acac61 --- /dev/null +++ b/hotspot/src/share/vm/utilities/resourceHash.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2015 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 "memory/allocation.hpp" +#include "memory/resourceArea.hpp" +#include "utilities/debug.hpp" +#include "utilities/resourceHash.hpp" + +#ifndef PRODUCT + +/////////////// Unit tests /////////////// + +class TestResourceHashtable : public AllStatic { + typedef void* K; + typedef int V; + + static unsigned identity_hash(const K& k) { + return (unsigned)(uintptr_t)k; + } + + static unsigned bad_hash(const K& k) { + return 1; + } + + class EqualityTestIter { + public: + bool do_entry(K const& k, V const& v) { + assert((uintptr_t)k == (uintptr_t)v, ""); + return true; // continue iteration + } + }; + + template< + unsigned (*HASH) (K const&) = primitive_hash, + bool (*EQUALS)(K const&, K const&) = primitive_equals, + unsigned SIZE = 256, + ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA, + MEMFLAGS MEM_TYPE = mtInternal + > + class Runner : public AllStatic { + static void* as_K(uintptr_t val) { return (void*)val; } + + public: + static void test_small() { + EqualityTestIter et; + ResourceHashtable rh; + + assert(!rh.contains(as_K(0x1)), ""); + + assert(rh.put(as_K(0x1), 0x1), ""); + assert(rh.contains(as_K(0x1)), ""); + + assert(!rh.put(as_K(0x1), 0x1), ""); + + assert(rh.put(as_K(0x2), 0x2), ""); + assert(rh.put(as_K(0x3), 0x3), ""); + assert(rh.put(as_K(0x4), 0x4), ""); + assert(rh.put(as_K(0x5), 0x5), ""); + + assert(!rh.remove(as_K(0x0)), ""); + rh.iterate(&et); + + assert(rh.remove(as_K(0x1)), ""); + rh.iterate(&et); + + } + + // We use keys with the low bits cleared since the default hash will do some shifting + static void test_small_shifted() { + EqualityTestIter et; + ResourceHashtable rh; + + assert(!rh.contains(as_K(0x10)), ""); + + assert(rh.put(as_K(0x10), 0x10), ""); + assert(rh.contains(as_K(0x10)), ""); + + assert(!rh.put(as_K(0x10), 0x10), ""); + + assert(rh.put(as_K(0x20), 0x20), ""); + assert(rh.put(as_K(0x30), 0x30), ""); + assert(rh.put(as_K(0x40), 0x40), ""); + assert(rh.put(as_K(0x50), 0x50), ""); + + assert(!rh.remove(as_K(0x00)), ""); + + assert(rh.remove(as_K(0x10)), ""); + + rh.iterate(&et); + } + + static void test(unsigned num_elements = SIZE) { + EqualityTestIter et; + ResourceHashtable rh; + + for (uintptr_t i = 0; i < num_elements; ++i) { + assert(rh.put(as_K(i), i), ""); + } + + rh.iterate(&et); + + for (uintptr_t i = num_elements; i > 0; --i) { + uintptr_t index = i - 1; + assert(rh.remove(as_K(index)), ""); + } + rh.iterate(&et); + for (uintptr_t i = num_elements; i > 0; --i) { + uintptr_t index = i - 1; + assert(!rh.remove(as_K(index)), ""); + } + rh.iterate(&et); + } + }; + + public: + static void run_tests() { + { + ResourceMark rm; + Runner<>::test_small(); + Runner<>::test_small_shifted(); + Runner<>::test(); + } + + { + ResourceMark rm; + Runner::test_small(); + Runner::test_small_shifted(); + Runner::test(); + } + + { + ResourceMark rm; + Runner::test_small(); + Runner::test_small_shifted(); + Runner::test(); + } + + + assert(Thread::current()->resource_area()->nesting() == 0, "this code depends on not having an active ResourceMark"); + // The following test calls will cause an assert if resource allocations occur since we don't have an active mark + Runner, primitive_equals, 512, ResourceObj::C_HEAP>::test_small(); + Runner, primitive_equals, 512, ResourceObj::C_HEAP>::test_small_shifted(); + Runner, primitive_equals, 512, ResourceObj::C_HEAP>::test(); + + Runner, 512, ResourceObj::C_HEAP>::test_small(); + Runner, 512, ResourceObj::C_HEAP>::test_small_shifted(); + Runner, 512, ResourceObj::C_HEAP>::test(); + + Runner, 1, ResourceObj::C_HEAP>::test_small(); + Runner, 1, ResourceObj::C_HEAP>::test_small_shifted(); + Runner, 1, ResourceObj::C_HEAP>::test(512); + } +}; + +void TestResourcehash_test() { + TestResourceHashtable::run_tests(); +} + +#endif // not PRODUCT + diff --git a/hotspot/src/share/vm/utilities/resourceHash.hpp b/hotspot/src/share/vm/utilities/resourceHash.hpp index 211d6bca117..82c1219b465 100644 --- a/hotspot/src/share/vm/utilities/resourceHash.hpp +++ b/hotspot/src/share/vm/utilities/resourceHash.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015 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 @@ -35,7 +35,7 @@ template struct ResourceHashtableFns { template unsigned primitive_hash(const K& k) { unsigned hash = (unsigned)((uintptr_t)k); - return hash ^ (hash > 3); // just in case we're dealing with aligned ptrs + return hash ^ (hash >> 3); // just in case we're dealing with aligned ptrs } template bool primitive_equals(const K& k0, const K& k1) { @@ -50,7 +50,9 @@ template< //typename ResourceHashtableFns::equals_fn EQUALS = primitive_equals, unsigned (*HASH) (K const&) = primitive_hash, bool (*EQUALS)(K const&, K const&) = primitive_equals, - unsigned SIZE = 256 + unsigned SIZE = 256, + ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA, + MEMFLAGS MEM_TYPE = mtInternal > class ResourceHashtable : public ResourceObj { private: @@ -91,6 +93,21 @@ class ResourceHashtable : public ResourceObj { public: ResourceHashtable() { memset(_table, 0, SIZE * sizeof(Node*)); } + ~ResourceHashtable() { + if (ALLOC_TYPE == C_HEAP) { + Node* const* bucket = _table; + while (bucket < &_table[SIZE]) { + Node* node = *bucket; + while (node != NULL) { + Node* cur = node; + node = node->_next; + delete cur; + } + ++bucket; + } + } + } + bool contains(K const& key) const { return get(key) != NULL; } @@ -117,11 +134,26 @@ class ResourceHashtable : public ResourceObj { (*ptr)->_value = value; return false; } else { - *ptr = new Node(hv, key, value); + *ptr = new (ALLOC_TYPE, MEM_TYPE) Node(hv, key, value); return true; } } + bool remove(K const& key) { + unsigned hv = HASH(key); + Node** ptr = lookup_node(hv, key); + + Node* node = *ptr; + if (node != NULL) { + *ptr = node->_next; + if (ALLOC_TYPE == C_HEAP) { + delete node; + } + return true; + } + return false; + } + // ITER contains bool do_entry(K const&, V const&), which will be // called for each entry in the table. If do_entry() returns false, // the iteration is cancelled. @@ -138,6 +170,10 @@ class ResourceHashtable : public ResourceObj { ++bucket; } } + + static size_t node_size() { + return sizeof(Node); + } }; diff --git a/hotspot/src/share/vm/utilities/utf8.cpp b/hotspot/src/share/vm/utilities/utf8.cpp index a0fbd95988e..d7a6043097a 100644 --- a/hotspot/src/share/vm/utilities/utf8.cpp +++ b/hotspot/src/share/vm/utilities/utf8.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ // Assume the utf8 string is in legal form and has been // checked in the class file parser/format checker. -char* UTF8::next(const char* str, jchar* value) { +template char* UTF8::next(const char* str, T* value) { unsigned const char *ptr = (const unsigned char *)str; unsigned char ch, ch2, ch3; int length = -1; /* bad length */ @@ -68,11 +68,11 @@ char* UTF8::next(const char* str, jchar* value) { } /* end of switch */ if (length <= 0) { - *value = ptr[0]; /* default bad result; */ + *value = (T)ptr[0]; /* default bad result; */ return (char*)(ptr + 1); // make progress somehow } - *value = result; + *value = (T)result; // The assert is correct but the .class file is wrong // assert(UNICODE::utf8_size(result) == length, "checking reverse computation"); @@ -96,12 +96,22 @@ char* UTF8::next_character(const char* str, jint* value) { // Count bytes of the form 10xxxxxx and deduct this count // from the total byte count. The utf8 string must be in // legal form which has been verified in the format checker. -int UTF8::unicode_length(const char* str, int len) { +int UTF8::unicode_length(const char* str, int len, bool& is_latin1, bool& has_multibyte) { int num_chars = len; + has_multibyte = false; + is_latin1 = true; + unsigned char prev = 0; for (int i = 0; i < len; i++) { - if ((str[i] & 0xC0) == 0x80) { + unsigned char c = str[i]; + if ((c & 0xC0) == 0x80) { + // Multibyte, check if valid latin1 character. + has_multibyte = true; + if (prev > 0xC3) { + is_latin1 = false; + } --num_chars; } + prev = c; } return num_chars; } @@ -110,17 +120,28 @@ int UTF8::unicode_length(const char* str, int len) { // 10xxxxxx which only appear in multibyte characters. // The utf8 string must be in legal form and has been // verified in the format checker. -int UTF8::unicode_length(const char* str) { +int UTF8::unicode_length(const char* str, bool& is_latin1, bool& has_multibyte) { int num_chars = 0; + has_multibyte = false; + is_latin1 = true; + unsigned char prev = 0; for (const char* p = str; *p; p++) { - if (((*p) & 0xC0) != 0x80) { + unsigned char c = (*p); + if ((c & 0xC0) == 0x80) { + // Multibyte, check if valid latin1 character. + has_multibyte = true; + if (prev > 0xC3) { + is_latin1 = false; + } + } else { num_chars++; } + prev = c; } return num_chars; } -// Writes a jchar a utf8 and returns the end +// Writes a jchar as utf8 and returns the end static u_char* utf8_write(u_char* base, jchar ch) { if ((ch != 0) && (ch <=0x7f)) { base[0] = (u_char) ch; @@ -145,7 +166,7 @@ static u_char* utf8_write(u_char* base, jchar ch) { return base + 3; } -void UTF8::convert_to_unicode(const char* utf8_str, jchar* unicode_str, int unicode_length) { +template void UTF8::convert_to_unicode(const char* utf8_str, T* unicode_str, int unicode_length) { unsigned char ch; const char *ptr = utf8_str; int index = 0; @@ -153,7 +174,7 @@ void UTF8::convert_to_unicode(const char* utf8_str, jchar* unicode_str, int unic /* ASCII case loop optimization */ for (; index < unicode_length; index++) { if((ch = ptr[0]) > 0x7F) { break; } - unicode_str[index] = ch; + unicode_str[index] = (T)ch; ptr = (const char *)(ptr + 1); } @@ -162,6 +183,12 @@ void UTF8::convert_to_unicode(const char* utf8_str, jchar* unicode_str, int unic } } +// Explicit instantiation for all supported string types. +template char* UTF8::next(const char* str, jchar* value); +template char* UTF8::next(const char* str, jbyte* value); +template void UTF8::convert_to_unicode(const char* utf8_str, jchar* unicode_str, int unicode_length); +template void UTF8::convert_to_unicode(const char* utf8_str, jbyte* unicode_str, int unicode_length); + // returns the quoted ascii length of a 0-terminated utf8 string int UTF8::quoted_ascii_length(const char* utf8_str, int utf8_length) { const char *ptr = utf8_str; @@ -306,9 +333,20 @@ jint UTF8::get_supplementary_character(const unsigned char* str) { + ((str[4] & 0x0f) << 6) + (str[5] & 0x3f); } - //------------------------------------------------------------------------------------- +bool UNICODE::is_latin1(jchar c) { + return (c <= 0x00FF); +} + +bool UNICODE::is_latin1(jchar* base, int length) { + for (int index = 0; index < length; index++) { + if (base[index] > 0x00FF) { + return false; + } + } + return true; +} int UNICODE::utf8_size(jchar c) { if ((0x0001 <= c) && (c <= 0x007F)) return 1; @@ -316,6 +354,11 @@ int UNICODE::utf8_size(jchar c) { return 3; } +int UNICODE::utf8_size(jbyte c) { + if (c >= 0x0001) return 1; + return 2; +} + int UNICODE::utf8_length(jchar* base, int length) { int result = 0; for (int index = 0; index < length; index++) { @@ -327,6 +370,15 @@ int UNICODE::utf8_length(jchar* base, int length) { return result; } +int UNICODE::utf8_length(jbyte* base, int length) { + int result = 0; + for (int index = 0; index < length; index++) { + jbyte c = base[index]; + result += utf8_size(c); + } + return result; +} + char* UNICODE::as_utf8(jchar* base, int length) { int utf8_len = utf8_length(base, length); u_char* buf = NEW_RESOURCE_ARRAY(u_char, utf8_len + 1); @@ -335,6 +387,26 @@ char* UNICODE::as_utf8(jchar* base, int length) { return result; } +char* UNICODE::as_utf8(jbyte* base, int length) { + int utf8_len = utf8_length(base, length); + u_char* result = NEW_RESOURCE_ARRAY(u_char, utf8_len + 1); + u_char* p = result; + if (utf8_len == length) { + for (int index = 0; index < length; index++) { + *p++ = base[index]; + } + } else { + // Unicode string contains U+0000 which should + // be encoded as 0xC080 in "modified" UTF8. + for (int index = 0; index < length; index++) { + p = utf8_write(p, ((jchar) base[index]) & 0xff); + } + } + *p = '\0'; + assert(p == &result[utf8_len], "length prediction must be correct"); + return (char*) result; +} + char* UNICODE::as_utf8(jchar* base, int length, char* buf, int buflen) { u_char* p = (u_char*)buf; for (int index = 0; index < length; index++) { @@ -347,6 +419,26 @@ char* UNICODE::as_utf8(jchar* base, int length, char* buf, int buflen) { return buf; } +char* UNICODE::as_utf8(jbyte* base, int length, char* buf, int buflen) { + u_char* p = (u_char*)buf; + u_char* end = (u_char*)buf + buflen; + for (int index = 0; index < length; index++) { + jbyte c = base[index]; + int sz = utf8_size(c); + buflen -= sz; + if (buflen <= 0) break; // string is truncated + if (sz == 1) { + *p++ = c; + } else { + // Unicode string contains U+0000 which should + // be encoded as 0xC080 in "modified" UTF8. + p = utf8_write(p, ((jchar) c) & 0xff); + } + } + *p = '\0'; + return buf; +} + void UNICODE::convert_to_utf8(const jchar* base, int length, char* utf8_buffer) { for(int index = 0; index < length; index++) { utf8_buffer = (char*)utf8_write((u_char*)utf8_buffer, base[index]); @@ -355,10 +447,11 @@ void UNICODE::convert_to_utf8(const jchar* base, int length, char* utf8_buffer) } // returns the quoted ascii length of a unicode string -int UNICODE::quoted_ascii_length(jchar* base, int length) { +template +int UNICODE::quoted_ascii_length(T* base, int length) { int result = 0; for (int i = 0; i < length; i++) { - jchar c = base[i]; + T c = base[i]; if (c >= 32 && c < 127) { result++; } else { @@ -368,12 +461,13 @@ int UNICODE::quoted_ascii_length(jchar* base, int length) { return result; } -// converts a utf8 string to quoted ascii -void UNICODE::as_quoted_ascii(const jchar* base, int length, char* buf, int buflen) { +// converts a unicode string to quoted ascii +template +void UNICODE::as_quoted_ascii(const T* base, int length, char* buf, int buflen) { char* p = buf; char* end = buf + buflen; for (int index = 0; index < length; index++) { - jchar c = base[index]; + T c = base[index]; if (c >= 32 && c < 127) { if (p + 1 >= end) break; // string is truncated *p++ = (char)c; @@ -386,6 +480,13 @@ void UNICODE::as_quoted_ascii(const jchar* base, int length, char* buf, int bufl *p = '\0'; } +// Explicit instantiation for all supported types. +template int UNICODE::quoted_ascii_length(jbyte* base, int length); +template int UNICODE::quoted_ascii_length(jchar* base, int length); +template void UNICODE::as_quoted_ascii(const jbyte* base, int length, char* buf, int buflen); +template void UNICODE::as_quoted_ascii(const jchar* base, int length, char* buf, int buflen); + + #ifndef PRODUCT void TestAsUtf8() { char res[60]; diff --git a/hotspot/src/share/vm/utilities/utf8.hpp b/hotspot/src/share/vm/utilities/utf8.hpp index 354941e6dc0..161eb410f40 100644 --- a/hotspot/src/share/vm/utilities/utf8.hpp +++ b/hotspot/src/share/vm/utilities/utf8.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,13 +33,21 @@ class UTF8 : AllStatic { public: // returns the unicode length of a 0-terminated utf8 string - static int unicode_length(const char* utf8_str); + static int unicode_length(const char* utf8_str) { + bool is_latin1, has_multibyte; + return unicode_length(utf8_str, is_latin1, has_multibyte); + } + static int unicode_length(const char* utf8_str, bool& is_latin1, bool& has_multibyte); // returns the unicode length of a non-0-terminated utf8 string - static int unicode_length(const char* utf8_str, int len); + static int unicode_length(const char* utf8_str, int len) { + bool is_latin1, has_multibyte; + return unicode_length(utf8_str, len, is_latin1, has_multibyte); + } + static int unicode_length(const char* utf8_str, int len, bool& is_latin1, bool& has_multibyte); // converts a utf8 string to a unicode string - static void convert_to_unicode(const char* utf8_str, jchar* unicode_buffer, int unicode_length); + template static void convert_to_unicode(const char* utf8_str, T* unicode_str, int unicode_length); // returns the quoted ascii length of a utf8 string static int quoted_ascii_length(const char* utf8_str, int utf8_length); @@ -53,7 +61,7 @@ class UTF8 : AllStatic { // decodes the current utf8 character, stores the result in value, // and returns the end of the current utf8 chararacter. - static char* next(const char* str, jchar* value); + template static char* next(const char* str, T* value); // decodes the current utf8 character, gets the supplementary character instead of // the surrogate pair when seeing a supplementary character in string, @@ -76,11 +84,19 @@ class UTF8 : AllStatic { class UNICODE : AllStatic { public: + // checks if the given unicode character can be encoded as latin1 + static bool is_latin1(jchar c); + + // checks if the given string can be encoded as latin1 + static bool is_latin1(jchar* base, int length); + // returns the utf8 size of a unicode character static int utf8_size(jchar c); + static int utf8_size(jbyte c); // returns the utf8 length of a unicode string static int utf8_length(jchar* base, int length); + static int utf8_length(jbyte* base, int length); // converts a unicode string to utf8 string static void convert_to_utf8(const jchar* base, int length, char* utf8_buffer); @@ -88,13 +104,15 @@ class UNICODE : AllStatic { // converts a unicode string to a utf8 string; result is allocated // in resource area unless a buffer is provided. static char* as_utf8(jchar* base, int length); + static char* as_utf8(jbyte* base, int length); static char* as_utf8(jchar* base, int length, char* buf, int buflen); + static char* as_utf8(jbyte* base, int length, char* buf, int buflen); // returns the quoted ascii length of a unicode string - static int quoted_ascii_length(jchar* base, int length); + template static int quoted_ascii_length(T* base, int length); - // converts a utf8 string to quoted ascii - static void as_quoted_ascii(const jchar* base, int length, char* buf, int buflen); + // converts a unicode string to quoted ascii + template static void as_quoted_ascii(const T* base, int length, char* buf, int buflen); }; #endif // SHARE_VM_UTILITIES_UTF8_HPP diff --git a/hotspot/src/share/vm/utilities/xmlstream.cpp b/hotspot/src/share/vm/utilities/xmlstream.cpp index 394c063e8b4..0233639fe85 100644 --- a/hotspot/src/share/vm/utilities/xmlstream.cpp +++ b/hotspot/src/share/vm/utilities/xmlstream.cpp @@ -340,18 +340,22 @@ void xmlStream::done_raw(const char* kind) { print_raw_cr(">"); } +// If you remove the PRAGMA, this fails to compile with clang-503.0.40. PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED // ------------------------------------------------------------------ void xmlStream::va_done(const char* format, va_list ap) { char buffer[200]; - guarantee(strlen(format) + 10 < sizeof(buffer), "bigger format buffer"); + size_t format_len = strlen(format); + guarantee(format_len + 10 < sizeof(buffer), "bigger format buffer"); const char* kind = format; const char* kind_end = strchr(kind, ' '); - size_t kind_len = (kind_end != NULL) ? (kind_end - kind) : strlen(kind); + size_t kind_len = (kind_end != NULL) ? (kind_end - kind) : format_len; strncpy(buffer, kind, kind_len); strcpy(buffer + kind_len, "_done"); - strcat(buffer, format + kind_len); + if (kind_end != NULL) { + strncat(buffer, format + kind_len, sizeof(buffer) - (kind_len + 5 /* _done */) - 1); + } // Output the trailing event with the timestamp. va_begin_elem(buffer, ap); stamp(); diff --git a/hotspot/test/Makefile b/hotspot/test/Makefile index c3aa134d84c..41538dec380 100644 --- a/hotspot/test/Makefile +++ b/hotspot/test/Makefile @@ -243,6 +243,9 @@ hotspot_%: $(ECHO) "Running tests: $@" $(MAKE) -j 1 TEST_SELECTION=":$@" UNIQUE_DIR=$@ jtreg_tests; +hotspot_internal: + $(ALT_OUTPUTDIR)/jdk/bin/java -XX:+ExecuteInternalVMTests -XX:+ShowMessageBoxOnError -version + # Prep for output prep: clean @$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR) diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index c361a5d8b9a..46a0b4098a1 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2015, 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,5 +32,9 @@ keys=cte_test jcmd nmt regression gc stress groups=TEST.groups [closed/TEST.groups] requires.properties=sun.arch.data.model -# Tests using jtreg 4.1 b11 features -requiredVersion=4.1 b11 +# Tests using jtreg 4.1 b12 features +requiredVersion=4.1 b12 + +# Path to libraries in the topmost test directory. This is needed so @library +# does not need ../../ notation to reach them +external.lib.roots = ../../ diff --git a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java index c99c3eae359..94102f45d0a 100644 --- a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseBMI1Instructions option on CPU with * BMI1 feature support. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestUseBMI1InstructionsOnSupportedCPU diff --git a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java index d935113bb5c..5581bdecc35 100644 --- a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseBMI1Instructions option on CPU without * BMI1 feature support. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestUseBMI1InstructionsOnUnsupportedCPU diff --git a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java index 86923048031..6f29097065a 100644 --- a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseCountLeadingZerosInstruction option * on CPU with LZCNT support. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestUseCountLeadingZerosInstructionOnSupportedCPU diff --git a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java index b774b0e5211..25ce1d916c3 100644 --- a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseCountLeadingZerosInstruction option * on CPU without LZCNT support. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestUseCountLeadingZerosInstructionOnUnsupportedCPU diff --git a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java index 7d3f6c6858a..81519c09a04 100644 --- a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseCountTrailingZerosInstruction option * on CPU with TZCNT (BMI1 feature) support. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestUseCountTrailingZerosInstructionOnSupportedCPU diff --git a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java index db09d2da5d4..0ffcf279149 100644 --- a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseCountTrailingZerosInstruction option * on CPU without TZCNT instruction (BMI1 feature) support. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestUseCountTrailingZerosInstructionOnUnsupportedCPU diff --git a/hotspot/test/compiler/arraycopy/TestArrayCopyNoInitDeopt.java b/hotspot/test/compiler/arraycopy/TestArrayCopyNoInitDeopt.java index dfa5f7e0414..c7caa21b237 100644 --- a/hotspot/test/compiler/arraycopy/TestArrayCopyNoInitDeopt.java +++ b/hotspot/test/compiler/arraycopy/TestArrayCopyNoInitDeopt.java @@ -25,7 +25,7 @@ * @test * @bug 8072016 * @summary Infinite deoptimization/recompilation cycles in case of arraycopy with tightly coupled allocation - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * @modules java.base/sun.misc * java.management * @build TestArrayCopyNoInitDeopt diff --git a/hotspot/test/compiler/c2/6589834/Test_ia32.java b/hotspot/test/compiler/c2/6589834/Test_ia32.java index 86b4314d113..d35c70d8a59 100644 --- a/hotspot/test/compiler/c2/6589834/Test_ia32.java +++ b/hotspot/test/compiler/c2/6589834/Test_ia32.java @@ -26,7 +26,7 @@ * @bug 6589834 * @summary Safepoint placed between stack pointer increment and decrement leads * to interpreter's stack corruption after deoptimization. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.compiler * java.management diff --git a/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java b/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java index aca9d76afb4..05a86f923b3 100644 --- a/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java +++ b/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java @@ -33,7 +33,7 @@ import java.net.URLConnection; * @test TestAnonymousClassUnloading * @bug 8054402 * @summary "Tests unloading of anonymous classes." - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * @compile TestAnonymousClassUnloading.java * @run main ClassFileInstaller TestAnonymousClassUnloading diff --git a/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java b/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java index d2cf51ee8bd..a824ec2bdb2 100644 --- a/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java +++ b/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java @@ -31,7 +31,7 @@ import java.net.URLClassLoader; * @test MethodUnloadingTest * @bug 8029443 * @summary "Tests the unloading of methods to to class unloading" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestMethodUnloading * @build WorkerClass * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java b/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java index a18f2c3c100..7c97cf30ea7 100644 --- a/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java +++ b/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java @@ -27,7 +27,7 @@ import sun.hotspot.WhiteBox; /* * @test CheckSegmentedCodeCache * @bug 8015774 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @summary "Checks VM options related to the segmented code cache" * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/codecache/OverflowCodeCacheTest.java b/hotspot/test/compiler/codecache/OverflowCodeCacheTest.java index bfc1775a3a3..85537e8d783 100644 --- a/hotspot/test/compiler/codecache/OverflowCodeCacheTest.java +++ b/hotspot/test/compiler/codecache/OverflowCodeCacheTest.java @@ -34,7 +34,7 @@ import jdk.test.lib.Asserts; /* * @test OverflowCodeCacheTest * @bug 8059550 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build OverflowCodeCacheTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/codecache/cli/TestSegmentedCodeCacheOption.java b/hotspot/test/compiler/codecache/cli/TestSegmentedCodeCacheOption.java index 0d77acae058..65079c600c5 100644 --- a/hotspot/test/compiler/codecache/cli/TestSegmentedCodeCacheOption.java +++ b/hotspot/test/compiler/codecache/cli/TestSegmentedCodeCacheOption.java @@ -30,7 +30,7 @@ import sun.hotspot.code.BlobType; * @test * @bug 8015774 * @summary Verify SegmentedCodeCache option's processing - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.compiler * java.management diff --git a/hotspot/test/compiler/codecache/cli/codeheapsize/TestCodeHeapSizeOptions.java b/hotspot/test/compiler/codecache/cli/codeheapsize/TestCodeHeapSizeOptions.java index 14a9171f66b..c96e80b59b5 100644 --- a/hotspot/test/compiler/codecache/cli/codeheapsize/TestCodeHeapSizeOptions.java +++ b/hotspot/test/compiler/codecache/cli/codeheapsize/TestCodeHeapSizeOptions.java @@ -31,7 +31,7 @@ import java.util.EnumSet; * @test * @bug 8015774 * @summary Verify processing of options related to code heaps sizing. - * @library /testlibrary .. /../../test/lib + * @library /testlibrary .. /test/lib * @modules java.base/sun.misc * java.compiler * java.management diff --git a/hotspot/test/compiler/codecache/cli/printcodecache/TestPrintCodeCacheOption.java b/hotspot/test/compiler/codecache/cli/printcodecache/TestPrintCodeCacheOption.java index 4eda68cd1fb..8d0162277f7 100644 --- a/hotspot/test/compiler/codecache/cli/printcodecache/TestPrintCodeCacheOption.java +++ b/hotspot/test/compiler/codecache/cli/printcodecache/TestPrintCodeCacheOption.java @@ -30,7 +30,7 @@ import java.util.EnumSet; * @test * @bug 8015774 * @summary Verify that PrintCodeCache option print correct information. - * @library /testlibrary .. /../../test/lib + * @library /testlibrary .. /test/lib * @modules java.base/sun.misc * java.compiler * java.management diff --git a/hotspot/test/compiler/codecache/dtrace/SegmentedCodeCacheDtraceTest.java b/hotspot/test/compiler/codecache/dtrace/SegmentedCodeCacheDtraceTest.java index 2269f3a4228..b8408ea3f8e 100644 --- a/hotspot/test/compiler/codecache/dtrace/SegmentedCodeCacheDtraceTest.java +++ b/hotspot/test/compiler/codecache/dtrace/SegmentedCodeCacheDtraceTest.java @@ -48,7 +48,7 @@ import java.util.stream.Collectors; * @test SegmentedCodeCacheDtraceTest * @bug 8015774 * @requires os.family=="solaris" - * @library /testlibrary / /../../test/lib + * @library /testlibrary / /test/lib * @build SegmentedCodeCacheDtraceTestWorker * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/codecache/jmx/BeanTypeTest.java b/hotspot/test/compiler/codecache/jmx/BeanTypeTest.java index b402ba5d590..bea23c6a52a 100644 --- a/hotspot/test/compiler/codecache/jmx/BeanTypeTest.java +++ b/hotspot/test/compiler/codecache/jmx/BeanTypeTest.java @@ -27,7 +27,7 @@ import sun.hotspot.code.BlobType; /** * @test BeanTypeTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build BeanTypeTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/codecache/jmx/CodeHeapBeanPresenceTest.java b/hotspot/test/compiler/codecache/jmx/CodeHeapBeanPresenceTest.java index 932d16de30a..faef9a2ead7 100644 --- a/hotspot/test/compiler/codecache/jmx/CodeHeapBeanPresenceTest.java +++ b/hotspot/test/compiler/codecache/jmx/CodeHeapBeanPresenceTest.java @@ -27,7 +27,7 @@ import sun.hotspot.code.BlobType; /** * @test CodeHeapBeanPresenceTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build CodeHeapBeanPresenceTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/codecache/jmx/GetUsageTest.java b/hotspot/test/compiler/codecache/jmx/GetUsageTest.java index d657699395c..a730f8c8ee0 100644 --- a/hotspot/test/compiler/codecache/jmx/GetUsageTest.java +++ b/hotspot/test/compiler/codecache/jmx/GetUsageTest.java @@ -29,7 +29,7 @@ import sun.hotspot.code.BlobType; /* * @test GetUsageTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build GetUsageTest diff --git a/hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java b/hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java index c47f7b17d2b..b58b5b0f6a7 100644 --- a/hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java +++ b/hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java @@ -29,7 +29,7 @@ import sun.hotspot.code.BlobType; /* * @test InitialAndMaxUsageTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build InitialAndMaxUsageTest diff --git a/hotspot/test/compiler/codecache/jmx/ManagerNamesTest.java b/hotspot/test/compiler/codecache/jmx/ManagerNamesTest.java index d3e8f781d12..4b3b597ec06 100644 --- a/hotspot/test/compiler/codecache/jmx/ManagerNamesTest.java +++ b/hotspot/test/compiler/codecache/jmx/ManagerNamesTest.java @@ -27,7 +27,7 @@ import sun.hotspot.code.BlobType; /** * @test ManagerNamesTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build ManagerNamesTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/codecache/jmx/MemoryPoolsPresenceTest.java b/hotspot/test/compiler/codecache/jmx/MemoryPoolsPresenceTest.java index 0d497006c2a..22eecc8adc6 100644 --- a/hotspot/test/compiler/codecache/jmx/MemoryPoolsPresenceTest.java +++ b/hotspot/test/compiler/codecache/jmx/MemoryPoolsPresenceTest.java @@ -32,7 +32,7 @@ import sun.hotspot.code.BlobType; /** * @test MemoryPoolsPresenceTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build MemoryPoolsPresenceTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java index e906b86f032..3bb001802ae 100644 --- a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java +++ b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java @@ -27,7 +27,7 @@ import sun.hotspot.code.BlobType; /* * @test PeakUsageTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build PeakUsageTest diff --git a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java index ee0fce1106c..69f10212a71 100644 --- a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java +++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java @@ -37,7 +37,7 @@ import sun.hotspot.code.BlobType; /* * @test PoolsIndependenceTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build PoolsIndependenceTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java index c5b9223ac10..d5c96601bc7 100644 --- a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java +++ b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java @@ -34,7 +34,7 @@ import sun.hotspot.code.BlobType; /* * @test ThresholdNotificationsTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build ThresholdNotificationsTest diff --git a/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededSeveralTimesTest.java b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededSeveralTimesTest.java index 3322ae642bc..8dd03969d33 100644 --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededSeveralTimesTest.java +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededSeveralTimesTest.java @@ -23,7 +23,7 @@ /* * @test UsageThresholdExceededSeveralTimesTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build UsageThresholdExceededTest diff --git a/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java index a699134c6cb..79a38cf8a4e 100644 --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java @@ -27,7 +27,7 @@ import sun.hotspot.code.BlobType; /* * @test UsageThresholdExceededTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build UsageThresholdExceededTest diff --git a/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java b/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java index 5fc45184b85..dc1af4d5e1f 100644 --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java @@ -27,7 +27,7 @@ import sun.hotspot.code.BlobType; /* * @test UsageThresholdIncreasedTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build UsageThresholdIncreasedTest diff --git a/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java b/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java index 23036cc1938..0481edfa77d 100644 --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java @@ -27,7 +27,7 @@ import sun.hotspot.code.BlobType; /* * @test UsageThresholdNotExceededTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build UsageThresholdNotExceededTest diff --git a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java index 8239a3852fe..520a02b01ab 100644 --- a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java +++ b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java @@ -29,7 +29,7 @@ import jdk.test.lib.Platform; /* * @test OverloadCompileQueueTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @ignore 8071905 diff --git a/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java b/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java index 400b99af378..7a02a7bd775 100644 --- a/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java +++ b/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java @@ -28,7 +28,7 @@ import sun.hotspot.code.BlobType; /* * @test RandomAllocationTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build RandomAllocationTest diff --git a/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java b/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java index d7c7f074d6d..6f7f0b0fd67 100644 --- a/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java +++ b/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java @@ -24,7 +24,7 @@ /* * @test UnexpectedDeoptimizationTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build UnexpectedDeoptimizationTest diff --git a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java index ab217789007..91329b1b29c 100644 --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java @@ -33,11 +33,12 @@ * @build sun.hotspot.WhiteBox.* * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=option,*.helper,bool,PrintAssembly,false -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOff + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:-PrintAssembly -XX:CompileCommand=option,*.helper,bool,PrintAssembly,false + * -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOff * @summary Test compiler control compatibility with compile command */ -// import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.dcmd.CommandExecutor; import jdk.test.lib.dcmd.JMXExecutor; diff --git a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java index ea7689c7fc7..bddbe6f4e3e 100644 --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java @@ -33,11 +33,12 @@ * @build sun.hotspot.WhiteBox.* * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=print,*.* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOn + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:-PrintAssembly -XX:CompileCommand=print,*.* -XX:+WhiteBoxAPI + * TestCompilerDirectivesCompatibilityCommandOn * @summary Test compiler control compatibility with compile command */ -// import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.dcmd.CommandExecutor; import jdk.test.lib.dcmd.JMXExecutor; diff --git a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java index 0ec10ba45d3..9715b1e4662 100644 --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java @@ -33,7 +33,8 @@ * @build sun.hotspot.WhiteBox.* * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run testng/othervm -Xbootclasspath/a:. -XX:+PrintAssembly -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityFlag + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+PrintAssembly -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityFlag * @summary Test compiler control compatibility with compile command */ diff --git a/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java b/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java index eff00e272db..e38ec6e8b83 100644 --- a/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java +++ b/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java @@ -40,7 +40,7 @@ import java.util.regex.Pattern; * @test * @bug 8135068 * @summary Tests CompilerCommand's method matcher - * @library /testlibrary /../../test/lib /compiler/whitebox ../share / + * @library /testlibrary /test/lib /compiler/whitebox ../share / * @build MethodMatcherTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/floatingpoint/TestPow2.java b/hotspot/test/compiler/floatingpoint/TestPow2.java index f46a9a717cc..ba019a8532a 100644 --- a/hotspot/test/compiler/floatingpoint/TestPow2.java +++ b/hotspot/test/compiler/floatingpoint/TestPow2.java @@ -25,7 +25,7 @@ * @test * @bug 8063086 * @summary X^2 special case for C2 yields different result than interpreter - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * @modules java.management * @build TestPow2 * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java b/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java index 1a547540382..8d85afe8466 100644 --- a/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java +++ b/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java @@ -26,7 +26,7 @@ import java.util.Objects; /* * @test * @bug 8130832 - * @library /testlibrary /../../test/lib /compiler/whitebox /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/whitebox /compiler/testlibrary * @build IntrinsicAvailableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java b/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java index 55d0897e2fc..cbf08bc465d 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of ANDN instruction - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestAndnI BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java b/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java index 33dd7a1f27b..088d537f633 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of ANDN instruction - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestAndnL BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java index c0768120911..4ec017795df 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSI instruction - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestBlsiI BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java index 6515496dbdb..3f19ace7a56 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSI instruction - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestBlsiL BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java index efbd0c7cb49..c2ad135f1ba 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSMSK instruction - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestBlsmskI BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java index c9a4cce706a..9753ff2a7b1 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSMSK instruction - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestBlsmskL BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java index 352c524497d..c877c87e969 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSR instruction - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestBlsrI BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java index fe4e0b4852a..514feced349 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSR instruction - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestBlsrL BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java b/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java index 4fb1a437fb8..e1104bd4aee 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of intrinsic - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestLzcntI BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java b/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java index 18f3c66afaf..9d3f48267f0 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of intrinsic - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestLzcntL BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java b/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java index caf3fb76106..76c2d8dc31c 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of intrinsic - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestTzcntI BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java b/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java index f56634f4322..76be757221a 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of intrinsic - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestTzcntL BMITestRunner Expr diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java index 04fe2f81115..f71f2153671 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build AddnTestI diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java index b9647cfb27c..9b64d8e4fbe 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build AddnTestL diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java index 3a583dfa463..f01b460b661 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build BlsiTestI diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java index 55696375968..ba9b027e20f 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build BlsiTestL diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java index aba4b327829..1e83c2db06a 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build BlsmskTestI diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java index b58e7b382d2..0a51b8a4761 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build BlsmskTestL diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java index 4b3434dc56f..b358d8b7741 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build BlsrTestI diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java index 81b9fa81c44..750ec7782b4 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build BlsrTestL diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java index dd45d49a3fd..c8a334dd923 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build LZcntTestI diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java index 4515d253aa0..e897eae1e0a 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build LZcntTestL diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java index 5d078b629f2..7b04578ae24 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build TZcntTestI diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java index 0758a441a2b..568e3fa4e0b 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /../../test/lib /compiler/whitebox .. + * @library /testlibrary /test/lib /compiler/whitebox .. * @modules java.base/sun.misc * java.management * @build TZcntTestL diff --git a/hotspot/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java b/hotspot/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java index f9f624f98fe..4815141f461 100644 --- a/hotspot/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java +++ b/hotspot/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java @@ -25,7 +25,7 @@ * @test NullCheckDroppingsTest * @bug 8054492 * @summary "Casting can result in redundant null checks in generated code" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.* diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java index 99948387c4d..62ba1ead758 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java index f13cabda852..3cb79cdb3e0 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java index 1569e13308d..7fb5e0f29ab 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java index 7dc1f329937..2b60cb03ee8 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java index f3b9df23778..66cc39170c3 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java index da230bbe6f4..b52ff29e171 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java index f529dfe8fad..998ebda8108 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java index 0829f1f67f0..dd5948f626d 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java index c0f07f51e16..de01cd3d1f6 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java index 7c8da0e65cb..7f773e8fa2a 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java index 23f10d69f19..f7e6589b2b8 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java index cf40b140f9d..eeefb81c8aa 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * /compiler/testlibrary * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java index 42cecbcd1eb..77f9fd274be 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA1Intrinsics option processing on supported CPU, - * @library /testlibrary /../../test/lib /compiler/testlibrary testcases + * @library /testlibrary /test/lib /compiler/testlibrary testcases * @modules java.base/sun.misc * java.management * @build TestUseSHA1IntrinsicsOptionOnSupportedCPU diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java index 56ed80671ad..5ca1f1a2ecf 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA1Intrinsics option processing on unsupported CPU, - * @library /testlibrary /../../test/lib /compiler/testlibrary testcases + * @library /testlibrary /test/lib /compiler/testlibrary testcases * @modules java.base/sun.misc * java.management * @build TestUseSHA1IntrinsicsOptionOnUnsupportedCPU diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java index dea1a34b110..bad4bf1bb9d 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA256Intrinsics option processing on supported CPU, - * @library /testlibrary /../../test/lib /compiler/testlibrary testcases + * @library /testlibrary /test/lib /compiler/testlibrary testcases * @modules java.base/sun.misc * java.management * @build TestUseSHA256IntrinsicsOptionOnSupportedCPU diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java index 741b00d3270..13c46a46a76 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA256Intrinsics option processing on unsupported CPU, - * @library /testlibrary /../../test/lib /compiler/testlibrary testcases + * @library /testlibrary /test/lib /compiler/testlibrary testcases * @modules java.base/sun.misc * java.management * @build TestUseSHA256IntrinsicsOptionOnUnsupportedCPU diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java index 192c08ce670..06851873f9e 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA512Intrinsics option processing on supported CPU. - * @library /testlibrary /../../test/lib /compiler/testlibrary testcases + * @library /testlibrary /test/lib /compiler/testlibrary testcases * @modules java.base/sun.misc * java.management * @build TestUseSHA512IntrinsicsOptionOnSupportedCPU diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java index 9f448616068..4d776611daa 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA512Intrinsics option processing on unsupported CPU, - * @library /testlibrary /../../test/lib /compiler/testlibrary testcases + * @library /testlibrary /test/lib /compiler/testlibrary testcases * @modules java.base/sun.misc * java.management * @build TestUseSHA512IntrinsicsOptionOnUnsupportedCPU diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java index d9f54215659..8c5bd2f0307 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA option processing on supported CPU, - * @library /testlibrary /../../test/lib /compiler/testlibrary testcases + * @library /testlibrary /test/lib /compiler/testlibrary testcases * @modules java.base/sun.misc * java.management * @build TestUseSHAOptionOnSupportedCPU diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java index 15ec6160e9c..e6d1161a1e6 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA option processing on unsupported CPU. - * @library /testlibrary /../../test/lib /compiler/testlibrary testcases + * @library /testlibrary /test/lib /compiler/testlibrary testcases * @modules java.base/sun.misc * java.management * @build TestUseSHAOptionOnUnsupportedCPU diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java index 9423521bb2a..c490762e2bf 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify that SHA-1 intrinsic is actually used. - * @library /testlibrary /../../test/lib /compiler/testlibrary ../ + * @library /testlibrary /test/lib /compiler/testlibrary ../ * @modules java.base/sun.misc * java.management * @build TestSHA intrinsics.Verifier TestSHA1Intrinsics diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java index 88c597240c4..4ebd58c7120 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-1 multi block intrinsic is actually used. - * @library /testlibrary /../../test/lib /compiler/testlibrary ../ + * @library /testlibrary /test/lib /compiler/testlibrary ../ * @modules java.base/sun.misc * java.management * @build TestSHA intrinsics.Verifier TestSHA1MultiBlockIntrinsics diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java index d579659f131..dc8a00f9c46 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-256 intrinsic is actually used. - * @library /testlibrary /../../test/lib /compiler/testlibrary ../ + * @library /testlibrary /test/lib /compiler/testlibrary ../ * @modules java.base/sun.misc * java.management * @build TestSHA intrinsics.Verifier TestSHA256Intrinsics diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java index 665d8d1f046..ba42a968d7c 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-256 multi block intrinsic is actually used. - * @library /testlibrary /../../test/lib /compiler/testlibrary ../ + * @library /testlibrary /test/lib /compiler/testlibrary ../ * @modules java.base/sun.misc * java.management * @build TestSHA intrinsics.Verifier TestSHA256MultiBlockIntrinsics diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java index 57a1cc9daa4..dbd78e157d5 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-512 intrinsic is actually used. - * @library /testlibrary /../../test/lib /compiler/testlibrary ../ + * @library /testlibrary /test/lib /compiler/testlibrary ../ * @modules java.base/sun.misc * java.management * @build TestSHA intrinsics.Verifier TestSHA512Intrinsics diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java index f6958d70862..00c8a40aa64 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-512 multi block intrinsic is actually used. - * @library /testlibrary /../../test/lib /compiler/testlibrary ../ + * @library /testlibrary /test/lib /compiler/testlibrary ../ * @modules java.base/sun.misc * java.management * @build TestSHA intrinsics.Verifier TestSHA512MultiBlockIntrinsics diff --git a/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics.java b/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics.java new file mode 100644 index 00000000000..9fe60b51d8d --- /dev/null +++ b/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics.java @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2015, 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. + */ + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.Arrays; + +/* + * @test + * @bug 8054307 + * @summary Tests correctness of string related intrinsics and C2 optimizations. + * @run main/timeout=240 TestStringIntrinsics + */ +public class TestStringIntrinsics { + + public enum Operation { + ARR_EQUALS_B, ARR_EQUALS_C, EQUALS, COMPARE_TO, INDEX_OF, INDEX_OF_CON_U, INDEX_OF_CON_L, + INDEX_OF_CON_UL, CONCAT, CONCAT_C, CONCAT_I, CONCAT_M, INDEX_OF_CHAR + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + @interface Test { + Operation op(); + String constString() default ""; + String[] inStrings() default {}; + char[] inChars() default {}; + int[] inInts() default {}; + String[] outStrings() default {}; + } + + public static void main(String[] args) throws Exception { + new TestStringIntrinsics().run(); + } + + public void run() throws Exception { + // Build latin1 and UTF16 strings + StringBuilder latin1Builder = new StringBuilder(); + for (int i = 0; i <= 255; ++i) { + latin1Builder.append((char) i); + } + String latin1 = latin1Builder.toString(); + StringBuilder utf16Builder = new StringBuilder(); + for (int i = 0; i <= 10000; ++i) { + utf16Builder.append((char) i); + } + String utf16 = utf16Builder.toString(); + + // Invoke test methods + for (Method m : TestStringIntrinsics.class.getMethods()) { + if (m.isAnnotationPresent(Test.class)) { + System.out.print("Checking " + m.getName() + "... "); + Operation op = m.getAnnotation(Test.class).op(); + Test antn = m.getAnnotation(Test.class); + if (isStringConcatTest(op)) { + checkStringConcat(op, m, antn); + } else { + checkIntrinsics(op, m, latin1, utf16, antn); + } + System.out.println("Done."); + } + } + } + + private boolean isStringConcatTest(Operation op) { + return op == Operation.CONCAT || + op == Operation.CONCAT_C || + op == Operation.CONCAT_I || + op == Operation.CONCAT_M; + } + + /** + * Checks correctness of the String.equals, String.compareTo and String.indexOf intrinsics. + * -XX:SpecialStringEquals + * -XX:SpecialStringCompareTo + * -XX:SpecialStringIndexOf + */ + private void checkIntrinsics(Operation op, Method m, String latin1, String utf16, Test antn) throws Exception { + for (int i = 0; i < 50_000; ++i) { + // Copy and permute latin1 and UTF16 string + char[] arrL = latin1.toCharArray(); + int indexL = i % arrL.length; + int mod = (arrL.length - arrL[indexL]); + int incL = i % ((mod != 0) ? mod : 1); + arrL[indexL] = (char) ((int) arrL[indexL] + incL); + String latin1Copy = String.valueOf(arrL); + + char[] arrU = utf16.toCharArray(); + int indexU = i % arrU.length; + mod = (arrU.length - arrU[indexU]); + int incU = i % ((mod != 0) ? mod : 1); + arrU[indexU] = (char) ((int) arrU[indexU] + incU); + String utf16Copy = String.valueOf(arrU); + + switch (op) { + case ARR_EQUALS_B: + invokeAndCheck(m, (incL == 0), latin1.getBytes("ISO-8859-1"), latin1Copy.getBytes("ISO-8859-1")); + invokeAndCheck(m, true, new byte[] {1, 2, 3}, new byte[] {1, 2, 3}); + invokeAndCheck(m, true, new byte[] {1}, new byte[] {1}); + invokeAndCheck(m, true, new byte[] {}, new byte[] {}); + break; + case ARR_EQUALS_C: + invokeAndCheck(m, (incU == 0), utf16.toCharArray(), arrU); + break; + case EQUALS: + invokeAndCheck(m, (incL == 0), latin1, latin1Copy); + invokeAndCheck(m, false, latin1, ""); + invokeAndCheck(m, false, "", latin1); + + invokeAndCheck(m, (incU == 0), utf16, utf16Copy); + invokeAndCheck(m, false, utf16, ""); + invokeAndCheck(m, false, "", utf16); + + invokeAndCheck(m, false, latin1, utf16); + break; + case COMPARE_TO: + invokeAndCheck(m, -incL, latin1, latin1Copy); + invokeAndCheck(m, latin1.length(), latin1, ""); + + invokeAndCheck(m, -incU, utf16, utf16Copy); + invokeAndCheck(m, utf16.length(), utf16, ""); + + // Cross coder + char cL = latin1.charAt(indexL); + char cU = utf16.charAt(indexU); + invokeAndCheck(m, cL - cU, latin1, latin1.replace(cL, cU)); + invokeAndCheck(m, cU - cL, utf16, utf16.replace(cU, cL)); + + // Different lengths + invokeAndCheck(m, 1, "ABCD", "ABC"); + invokeAndCheck(m, -1, "\uff21\uff22\uff23", "\uff21\uff22\uff23\uff24"); + invokeAndCheck(m, 1, "ABC\uff24", "ABC"); + invokeAndCheck(m, 3, "ABC\uff24\uff25\uff26", "ABC"); + invokeAndCheck(m, -1, "ABC","ABC\uff24"); + invokeAndCheck(m, -3, "ABC","ABC\uff24\uff25\uff26"); + break; + case INDEX_OF: + invokeAndCheck(m, indexL, latin1, latin1.substring(indexL), (indexL > 42) ? 42 : 0); + invokeAndCheck(m, 0, latin1, "", 0); + + invokeAndCheck(m, indexU, utf16, utf16.substring(indexU), (indexU > 42) ? 42 : 0); + invokeAndCheck(m, 0, utf16, "", 0); + + // Cross coder + invokeAndCheck(m, -1, latin1.substring(0, indexL), utf16.substring(indexU), (indexL > 42) ? 42 : 0); + // Skip latin1 chars in utf16 string + int start = 256; + int end = indexU > start ? indexU : start; + invokeAndCheck(m, end-start, utf16.substring(start, end) + latin1.substring(indexL), latin1.substring(indexL), 0); + break; + case INDEX_OF_CON_L: + invokeAndCheck(m, antn.constString(), latin1); + break; + case INDEX_OF_CON_U: + invokeAndCheck(m, antn.constString(), utf16); + break; + case INDEX_OF_CON_UL: + invokeAndCheck(m, antn.constString(), utf16); + break; + case INDEX_OF_CHAR: + invokeAndCheck(m, 7, "abcdefg\uD800\uDC00", 65536, 0); + invokeAndCheck(m, -1, "abcdefg\uD800\uDC01", 65536, 0); + invokeAndCheck(m, -1, "abcdefg\uD800", 65536, 0); + invokeAndCheck(m, 3, "abc\u0107", 263, 0); + invokeAndCheck(m, -1, "abc\u0108", 263, 0); + invokeAndCheck(m, 7, "abcdefg\u0107", 263, 0); + invokeAndCheck(m, 7, "abcdefg\u0107", 263, -1); + invokeAndCheck(m, 0, "\u0107", 263, 0); + break; + default: + throw new RuntimeException("Unexpected operation."); + } + } + } + + /** + * Checks correctness of the C2 string concatenation optimization. + * -XX:OptimizeStringConcat + */ + private void checkStringConcat(Operation op, Method m, Test antn) throws Exception { + for (int i = 0; i < 50_000; ++i) { + String[] result = antn.outStrings(); + switch(op) { + case CONCAT: + String[] strs = antn.inStrings(); + for (int j = 0; j < strs.length; ++j) { + invokeAndCheck(m, result[j], strs[j]); + } + break; + case CONCAT_C: + char[] ch = antn.inChars(); + for (int j = 0; j < ch.length; ++j) { + invokeAndCheck(m, result[j], ch[j]); + } + break; + case CONCAT_I: + int[] k = antn.inInts(); + for (int j = 0; j < k.length; ++j) { + invokeAndCheck(m, result[j], k[j]); + } + break; + case CONCAT_M: + strs = antn.inStrings(); + ch = antn.inChars(); + k = antn.inInts(); + for (int j = 0; j < strs.length; ++j) { + invokeAndCheck(m, result[j], strs[j], ch[j], k[j]); + } + break; + default: + throw new RuntimeException("Unexpected operation."); + } + } + } + + /** + * Invokes method 'm' by passing arguments 'args' and checks if the + * returned value equals 'expectedResult'. + */ + private void invokeAndCheck(Method m, Object expectedResult, Object... args) throws Exception { + Object result = m.invoke(null, args); + if (!result.equals(expectedResult)) { +// System.out.println("Expected:"); +// System.out.println(expectedResult); +// System.out.println("Returned:"); +// System.out.println(result); + throw new RuntimeException("Result of '" + m.getName() + "' not equal to expected value."); + } + } + + /* + * Constants + */ + static final char charU = '\uff21'; + static final char charL = 'A'; + static final String emptyString = ""; + static final String stringL = "abcdefghijklmnop"; + static final String stringSmallL = "abc"; + static final String stringU = "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"; + static final String stringSmallU = "\u0f21\u0f22\u0f23"; + static final int constInt = 123; + static final int constIntNeg = -123; + + /* + * Arrays.equals + */ + @Test(op = Operation.ARR_EQUALS_B) + public static boolean arrayEqualsB(byte[] a, byte[] b) { + return Arrays.equals(a, b); + } + + @Test(op = Operation.ARR_EQUALS_C) + public static boolean arrayEqualsC(char[] a, char[] b) { + return Arrays.equals(a, b); + } + + /* + * String.equals + */ + @Test(op = Operation.EQUALS) + public static boolean equals(String a, String b) { + return a.equals(b); + } + + /* + * String.compareTo + */ + @Test(op = Operation.COMPARE_TO) + public static int compareTo(String a, String b) { + return a.compareTo(b); + } + + /* + * String.indexOf + */ + @Test(op = Operation.INDEX_OF) + public static int indexOf(String a, String b, int from) { + return a.indexOf(b, from); + } + + @Test(op = Operation.INDEX_OF_CON_U, constString = stringSmallU) + public static String indexOfConstU(String a) { + int result = a.indexOf(stringSmallU); + return a.substring(result, result + stringSmallU.length()); + } + + @Test(op = Operation.INDEX_OF_CON_U, constString = stringU) + public static String indexOfConstLargeU(String a) { + int result = a.indexOf(stringU); + return a.substring(result, result + stringU.length()); + } + + @Test(op = Operation.INDEX_OF_CON_U, constString = emptyString) + public static String indexOfConstEmptyU(String a) { + int result = a.indexOf(emptyString); + return a.substring(result, result + emptyString.length()); + } + + @Test(op = Operation.INDEX_OF_CON_L, constString = stringSmallL) + public static String indexOfConstL(String a) { + int result = a.indexOf(stringSmallL); + return a.substring(result, result + stringSmallL.length()); + } + + @Test(op = Operation.INDEX_OF_CON_L, constString = stringL) + public static String indexOfConstLargeL(String a) { + int result = a.indexOf(stringL); + return a.substring(result, result + stringL.length()); + } + + @Test(op = Operation.INDEX_OF_CON_L, constString = emptyString) + public static String indexOfConstEmptyL(String a) { + int result = a.indexOf(emptyString); + return a.substring(result, result + emptyString.length()); + } + + @Test(op = Operation.INDEX_OF_CON_UL, constString = stringSmallL) + public static String indexOfConstUL(String a) { + int result = a.indexOf(stringSmallL); + return a.substring(result, result + stringSmallL.length()); + } + + @Test(op = Operation.INDEX_OF_CON_UL, constString = stringL) + public static String indexOfConstLargeUL(String a) { + int result = a.indexOf(stringL); + return a.substring(result, result + stringL.length()); + } + + @Test(op = Operation.INDEX_OF_CHAR) + public static int indexOfChar(String a, int ch, int from) { + return a.indexOf(ch, from); + } + + /* + * String concatenation optimization + */ + @Test(op = Operation.CONCAT, inStrings = {"ABC", "\uff21\uff22\uff23"}, outStrings = {"ABC", "\uff21\uff22\uff23"}) + public static String concatString(String a) { + return new StringBuilder().append(a).toString(); + } + + @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {""}) + public static String concatStringEmpty(String a) { + return new StringBuilder().toString(); + } + + @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {"null"}) + public static String concatStringNull(String a) { + return new StringBuilder().append((String)null).toString(); + } + + @Test(op = Operation.CONCAT, inStrings = {"ABC", "\uff21\uff22\uff23"}, outStrings = {"abcdefghijklmnopABCabc", "abcdefghijklmnop\uff21\uff22\uff23abc"}) + public static String concatStringConstL(String a) { + return new StringBuilder().append(stringL).append(a).append(stringSmallL).toString(); + } + + @Test(op = Operation.CONCAT, inStrings = {"ABC", "\uff21\uff22\uff23"}, outStrings = {"\u0f21\u0f22\u0f23ABC\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28", "\u0f21\u0f22\u0f23\uff21\uff22\uff23\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"}) + public static String concatStringConstU(String a) { + return new StringBuilder().append(stringSmallU).append(a).append(stringU).toString(); + } + + @Test(op = Operation.CONCAT_C, inChars = {'A', '\uff21'}, outStrings = {"A", "\uff21"}) + public static String concatChar(char a) { + return new StringBuilder().append(a).toString(); + } + + @Test(op = Operation.CONCAT_C, inChars = {'A', '\uff21'}, outStrings = {"abcdefghijklmnopAabcA\uff21", "abcdefghijklmnop\uff21abcA\uff21"}) + public static String concatCharConstL(char a) { + return new StringBuilder().append(stringL).append(a).append(stringSmallL).append(charL).append(charU).toString(); + } + + @Test(op = Operation.CONCAT_C, inChars = {'A', '\uff21'}, outStrings = {"\u0f21\u0f22\u0f23A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21A", "\u0f21\u0f22\u0f23\uff21\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21A"}) + public static String concatCharConstU(char a) { + return new StringBuilder().append(stringSmallU).append(a).append(stringU).append(charU).append(charL).toString(); + } + + @Test(op = Operation.CONCAT_I, inInts = {Integer.MIN_VALUE, -42, 42, Integer.MAX_VALUE}, outStrings = {"-2147483648", "-42", "42", "2147483647"}) + public static String concatInt(int a) { + return new StringBuilder().append(a).toString(); + } + + @Test(op = Operation.CONCAT_I, inInts = {Integer.MIN_VALUE, -42, 42, Integer.MAX_VALUE}, outStrings = {"abcdefghijklmnop-2147483648abc123-123", "abcdefghijklmnop-42abc123-123", "abcdefghijklmnop42abc123-123", "abcdefghijklmnop2147483647abc123-123"}) + public static String concatIntConstL(int b) { + return new StringBuilder().append(stringL).append(b).append(stringSmallL).append(constInt).append(constIntNeg).toString(); + } + + @Test(op = Operation.CONCAT_I, inInts = {Integer.MIN_VALUE, -42, 42, Integer.MAX_VALUE}, outStrings = {"\u0f21\u0f22\u0f23-2147483648\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123", "\u0f21\u0f22\u0f23-42\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123", "\u0f21\u0f22\u0f2342\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123", "\u0f21\u0f22\u0f232147483647\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123"}) + public static String concatIntConstU(int b) { + return new StringBuilder().append(stringSmallU).append(b).append(stringU).append(constInt).append(constIntNeg).toString(); + } + + @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {"nullabcabcdefghijklmnopA123-123"}) + public static String concatConstL(String a) { + return new StringBuilder().append((String)null).append(stringSmallL).append(stringL).append(charL).append(constInt).append(constIntNeg).toString(); + } + + @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {"nullabcabcdefghijklmnop\u0f21\u0f22\u0f23\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28A\uff21123-123"}) + public static String concatConstU(String a) { + return new StringBuilder().append((String)null).append(stringSmallL).append(stringL).append(stringSmallU).append(stringU).append(charL).append(charU).append(constInt).append(constIntNeg).toString(); + } + + @Test(op = Operation.CONCAT_M, + inStrings = {"ABCDEFG", "ABCDEFG", "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28", "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"}, + inChars = {'A', '\uff21', 'A', '\uff21'}, + inInts = {Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE}, + outStrings = {"ABCDEFGA-2147483648nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21ABCDEFGA-2147483648null", + "ABCDEFG\uff212147483647nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21ABCDEFG\uff212147483647null", + "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28A-2147483648nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28A-2147483648null", + "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff212147483647nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff212147483647null"}) + public static String concatMixed(String a, char b, int c) { + return new StringBuilder().append(a).append(b).append(c).append((String)null) + .append(stringL).append(constInt).append(constIntNeg).append(charL).append(stringU).append(charU) + .append(a).append(b).append(c).append((String)null).toString(); + } +} diff --git a/hotspot/test/compiler/intrinsics/unsafe/HeapByteBufferTest.java b/hotspot/test/compiler/intrinsics/unsafe/HeapByteBufferTest.java index 12af053737b..c9c0fc7506f 100644 --- a/hotspot/test/compiler/intrinsics/unsafe/HeapByteBufferTest.java +++ b/hotspot/test/compiler/intrinsics/unsafe/HeapByteBufferTest.java @@ -23,21 +23,22 @@ // // -import jdk.test.lib.Utils; -import static java.lang.Math.abs; +import java.nio.BufferOverflowException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import static java.nio.ByteOrder.BIG_ENDIAN; import static java.nio.ByteOrder.LITTLE_ENDIAN; -import java.util.Random; +import java.nio.ByteOrder; import java.util.Arrays; +import java.util.Random; +import jdk.test.lib.Utils; /** * @test * @bug 8026049 * @library /testlibrary - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-UseUnalignedAccesses HeapByteBufferTest - * @run main/othervm HeapByteBufferTest + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-UseUnalignedAccesses -Djdk.test.lib.random.seed=0 HeapByteBufferTest + * @run main/othervm -Djdk.test.lib.random.seed=0 HeapByteBufferTest * @summary Verify that byte buffers are correctly accessed. */ @@ -345,7 +346,149 @@ public class HeapByteBufferTest implements Runnable { return result; } + enum PrimitiveType { + BYTE(1), CHAR(2), SHORT(2), INT(4), LONG(8), FLOAT(4), DOUBLE(8); + + public final int size; + PrimitiveType(int size) { + this.size = size; + } + } + + void getOne(ByteBuffer b, PrimitiveType t) { + switch (t) { + case BYTE: b.get(); break; + case CHAR: b.getChar(); break; + case SHORT: b.getShort(); break; + case INT: b.getInt(); break; + case LONG: b.getLong(); break; + case FLOAT: b.getFloat(); break; + case DOUBLE: b.getDouble(); break; + } + } + + void putOne(ByteBuffer b, PrimitiveType t) { + switch (t) { + case BYTE: b.put((byte)0); break; + case CHAR: b.putChar('0'); break; + case SHORT: b.putShort((short)0); break; + case INT: b.putInt(0); break; + case LONG: b.putLong(0); break; + case FLOAT: b.putFloat(0); break; + case DOUBLE: b.putDouble(0); break; + } + } + + void getOne(ByteBuffer b, PrimitiveType t, int index) { + switch (t) { + case BYTE: b.get(index); break; + case CHAR: b.getChar(index); break; + case SHORT: b.getShort(index); break; + case INT: b.getInt(index); break; + case LONG: b.getLong(index); break; + case FLOAT: b.getFloat(index); break; + case DOUBLE: b.getDouble(index); break; + } + } + + void putOne(ByteBuffer b, PrimitiveType t, int index) { + switch (t) { + case BYTE: b.put(index, (byte)0); break; + case CHAR: b.putChar(index, '0'); break; + case SHORT: b.putShort(index, (short)0); break; + case INT: b.putInt(index, 0); break; + case LONG: b.putLong(index, 0); break; + case FLOAT: b.putFloat(index, 0); break; + case DOUBLE: b.putDouble(index, 0); break; + } + } + + void checkBoundaryConditions() { + for (int i = 0; i < 100; i++) { + int bufSize = random.nextInt(16); + byte[] bytes = new byte[bufSize]; + ByteBuffer buf = ByteBuffer.wrap(bytes); + for (int j = 0; j < 100; j++) { + int offset = random.nextInt(32) - 8; + for (PrimitiveType t : PrimitiveType.values()) { + int threw = 0; + try { + try { + buf.position(offset); + getOne(buf, t); + } catch (BufferUnderflowException e) { + if (offset + t.size < bufSize) + throw new RuntimeException + ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e); + threw++; + } catch (IllegalArgumentException e) { + if (offset >= 0 && offset + t.size < bufSize) + throw new RuntimeException + ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e); + threw++; + } + + try { + buf.position(offset); + putOne(buf, t); + } catch (BufferOverflowException e) { + if (offset + t.size < bufSize) + throw new RuntimeException + ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e); + threw++; + } catch (IllegalArgumentException e) { + if (offset >= 0 && offset + t.size < bufSize) + throw new RuntimeException + ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e); + threw++; + } + + try { + putOne(buf, t, offset); + } catch (IndexOutOfBoundsException e) { + if (offset >= 0 && offset + t.size < bufSize) + throw new RuntimeException + ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e); + threw++; + } + + try { + getOne(buf, t, offset); + } catch (IndexOutOfBoundsException e) { + if (offset >= 0 && offset + t.size < bufSize) + throw new RuntimeException + ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e); + threw++; + } + + if (threw == 0) { + // Make sure that we should not have thrown. + if (offset < 0 || offset + t.size > bufSize) { + throw new RuntimeException + ("should have thrown but did not, type = " + t + + ", offset = " + offset + ", bufSize = " + bufSize); + } + } else if (threw != 4) { + // If one of the {get,put} operations threw + // due to an invalid offset then all four of + // them should have thrown. + throw new RuntimeException + ("should have thrown but at least one did not, type = " + t + + ", offset = " + offset + ", bufSize = " + bufSize); + } + } catch (Throwable th) { + throw new RuntimeException + ("unexpected throw: type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, th); + + } + } + } + } + } + public void run() { + checkBoundaryConditions(); + for (int i = 0; i < data.capacity(); i += 8) { data.putLong(i, random.nextLong()); } diff --git a/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java b/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java index c6e40a8cb9d..2e2618b5c44 100644 --- a/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java +++ b/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java @@ -26,33 +26,42 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * @library /testlibrary /test/lib / + * @compile ./common/CompilerToVMHelper.java + * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:. + * -XX:+EnableJVMCI * compiler.jvmci.SecurityRestrictionsTest * NO_SEC_MAN - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:. + * -XX:+EnableJVMCI * compiler.jvmci.SecurityRestrictionsTest * NO_PERM - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:. + * -XX:+EnableJVMCI * compiler.jvmci.SecurityRestrictionsTest * ALL_PERM - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:. + * -XX:+EnableJVMCI * compiler.jvmci.SecurityRestrictionsTest * NO_JVMCI_ACCESS_PERM - * @run main/othervm -XX:+UnlockExperimentalVMOptions + * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:. + * -XX:-EnableJVMCI * compiler.jvmci.SecurityRestrictionsTest * NO_JVMCI */ package compiler.jvmci; -import jdk.vm.ci.hotspot.CompilerToVM; import jdk.test.lib.Utils; import java.lang.InternalError; +import java.lang.reflect.Constructor; import java.security.AccessControlException; import java.security.Permission; import java.util.PropertyPermission; import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; public class SecurityRestrictionsTest { @@ -164,7 +173,14 @@ public class SecurityRestrictionsTest { } } }; - Utils.runAndCheckException(CompilerToVM::new, exceptionCheck); + Utils.runAndCheckException(() -> { + try { + // CompilerToVM:: provokes CompilerToVM:: + Class.forName("jdk.vm.ci.hotspot.CompilerToVMHelper"); + } catch (ClassNotFoundException e) { + throw new Error("TESTBUG : " + e, e); + } + }, exceptionCheck); } public SecurityManager getSecurityManager() { diff --git a/hotspot/test/compiler/jvmci/common/CTVMUtilities.java b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java index 02fa6b1cf19..2563b35e5a5 100644 --- a/hotspot/test/compiler/jvmci/common/CTVMUtilities.java +++ b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java @@ -27,15 +27,16 @@ import java.lang.reflect.Field; import java.lang.reflect.Executable; import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; public class CTVMUtilities { /* * A method to return HotSpotResolvedJavaMethod object using class object * and method as input */ - public static HotSpotResolvedJavaMethodImpl getResolvedMethod(Class cls, + public static HotSpotResolvedJavaMethod getResolvedMethod(Class cls, Executable method) { if (!(method instanceof Method || method instanceof Constructor)) { throw new Error("wrong executable type " + method.getClass()); @@ -54,8 +55,20 @@ public class CTVMUtilities { return CompilerToVMHelper.getResolvedJavaMethodAtSlot(cls, slot); } - public static HotSpotResolvedJavaMethodImpl getResolvedMethod( + public static HotSpotResolvedJavaMethod getResolvedMethod( Executable method) { return getResolvedMethod(method.getDeclaringClass(), method); } + + public static InstalledCode getInstalledCode(String name, long address, + long entryPoint) { + return new InstalledCodeStub(name, address, entryPoint); + } + private static class InstalledCodeStub extends InstalledCode { + private InstalledCodeStub(String name, long address, long entryPoint) { + super(name); + this.address = address; + this.entryPoint = entryPoint; + } + } } diff --git a/hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java b/hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java index 2e12233a486..b5f4574b3a0 100644 --- a/hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java +++ b/hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java @@ -26,115 +26,120 @@ package jdk.vm.ci.hotspot; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.SpeculationLog; -/* +/** * A simple "proxy" class to get test access to CompilerToVM package-private methods */ public class CompilerToVMHelper { public static final CompilerToVM CTVM = new CompilerToVM(); - public static byte[] getBytecode(HotSpotResolvedJavaMethodImpl method) { - return CTVM.getBytecode(method); + public static byte[] getBytecode(HotSpotResolvedJavaMethod method) { + return CTVM.getBytecode((HotSpotResolvedJavaMethodImpl)method); } - public static int getExceptionTableLength(HotSpotResolvedJavaMethodImpl method) { - return CTVM.getExceptionTableLength(method); + public static int getExceptionTableLength(HotSpotResolvedJavaMethod method) { + return CTVM.getExceptionTableLength((HotSpotResolvedJavaMethodImpl)method); } - public static long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method) { - return CTVM.getExceptionTableStart(method); + public static long getExceptionTableStart(HotSpotResolvedJavaMethod method) { + return CTVM.getExceptionTableStart((HotSpotResolvedJavaMethodImpl)method); } - public static boolean canInlineMethod(HotSpotResolvedJavaMethodImpl method) { - return CTVM.canInlineMethod(method); + public static boolean canInlineMethod(HotSpotResolvedJavaMethod method) { + return CTVM.canInlineMethod((HotSpotResolvedJavaMethodImpl)method); } - public static boolean shouldInlineMethod(HotSpotResolvedJavaMethodImpl method) { - return CTVM.shouldInlineMethod(method); + public static boolean shouldInlineMethod(HotSpotResolvedJavaMethod method) { + return CTVM.shouldInlineMethod((HotSpotResolvedJavaMethodImpl)method); } - public static HotSpotResolvedJavaMethodImpl findUniqueConcreteMethod( - HotSpotResolvedObjectTypeImpl actualHolderType, - HotSpotResolvedJavaMethodImpl method) { - return CTVM.findUniqueConcreteMethod(actualHolderType, method); + public static HotSpotResolvedJavaMethod findUniqueConcreteMethod( + HotSpotResolvedObjectType actualHolderType, + HotSpotResolvedJavaMethod method) { + return CTVM.findUniqueConcreteMethod((HotSpotResolvedObjectTypeImpl) actualHolderType, (HotSpotResolvedJavaMethodImpl)method); } - public static HotSpotResolvedObjectTypeImpl getImplementor(HotSpotResolvedObjectTypeImpl type) { - return CTVM.getImplementor(type); + public static HotSpotResolvedObjectType getImplementor(HotSpotResolvedObjectType type) { + return CTVM.getImplementor((HotSpotResolvedObjectTypeImpl) type); } - public static boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethodImpl method) { - return CTVM.methodIsIgnoredBySecurityStackWalk(method); + public static boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethod method) { + return CTVM.methodIsIgnoredBySecurityStackWalk((HotSpotResolvedJavaMethodImpl)method); } - public static HotSpotResolvedObjectTypeImpl lookupType(String name, + public static HotSpotResolvedObjectType lookupType(String name, Class accessingClass, boolean resolve) { return CTVM.lookupType(name, accessingClass, resolve); } - public static Object resolveConstantInPool(HotSpotConstantPool constantPool, int cpi) { - return CTVM.resolveConstantInPool(constantPool, cpi); + public static Object resolveConstantInPool(ConstantPool constantPool, int cpi) { + return CTVM.resolveConstantInPool((HotSpotConstantPool) constantPool, cpi); } - public static Object resolvePossiblyCachedConstantInPool(HotSpotConstantPool constantPool, int cpi) { - return CTVM.resolvePossiblyCachedConstantInPool(constantPool, cpi); + public static Object resolvePossiblyCachedConstantInPool(ConstantPool constantPool, int cpi) { + return CTVM.resolvePossiblyCachedConstantInPool((HotSpotConstantPool) constantPool, cpi); } - public static int lookupNameAndTypeRefIndexInPool(HotSpotConstantPool constantPool, int cpi) { - return CTVM.lookupNameAndTypeRefIndexInPool(constantPool, cpi); + public static int lookupNameAndTypeRefIndexInPool(ConstantPool constantPool, int cpi) { + return CTVM.lookupNameAndTypeRefIndexInPool((HotSpotConstantPool) constantPool, cpi); } - public static String lookupNameInPool(HotSpotConstantPool constantPool, int cpi) { - return CTVM.lookupNameInPool(constantPool, cpi); + public static String lookupNameInPool(ConstantPool constantPool, int cpi) { + return CTVM.lookupNameInPool((HotSpotConstantPool) constantPool, cpi); } - public static String lookupSignatureInPool(HotSpotConstantPool constantPool, int cpi) { - return CTVM.lookupSignatureInPool(constantPool, cpi); + public static String lookupSignatureInPool(ConstantPool constantPool, int cpi) { + return CTVM.lookupSignatureInPool((HotSpotConstantPool) constantPool, cpi); } - public static int lookupKlassRefIndexInPool(HotSpotConstantPool constantPool, int cpi) { - return CTVM.lookupKlassRefIndexInPool(constantPool, cpi); + public static int lookupKlassRefIndexInPool(ConstantPool constantPool, int cpi) { + return CTVM.lookupKlassRefIndexInPool((HotSpotConstantPool) constantPool, cpi); } - public static Object lookupKlassInPool(HotSpotConstantPool constantPool, int cpi) { - return CTVM.lookupKlassInPool(constantPool, cpi); + public static Object lookupKlassInPool(ConstantPool constantPool, int cpi) { + return CTVM.lookupKlassInPool((HotSpotConstantPool) constantPool, cpi); } - public static HotSpotResolvedJavaMethodImpl lookupMethodInPool( - HotSpotConstantPool constantPool, int cpi, byte opcode) { - return CTVM.lookupMethodInPool(constantPool, cpi, opcode); + public static HotSpotResolvedJavaMethod lookupMethodInPool( + ConstantPool constantPool, int cpi, byte opcode) { + return CTVM.lookupMethodInPool((HotSpotConstantPool) constantPool, cpi, opcode); } - public static void resolveInvokeDynamicInPool(HotSpotConstantPool constantPool, int cpi) { - CTVM.resolveInvokeDynamicInPool(constantPool, cpi); + public static void resolveInvokeDynamicInPool( + ConstantPool constantPool, int cpi) { + CTVM.resolveInvokeDynamicInPool((HotSpotConstantPool) constantPool, cpi); } - public static void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi) { - CTVM.resolveInvokeHandleInPool(constantPool, cpi); + public static void resolveInvokeHandleInPool( + ConstantPool constantPool, int cpi) { + CTVM.resolveInvokeHandleInPool((HotSpotConstantPool) constantPool, cpi); } - public static HotSpotResolvedObjectTypeImpl resolveTypeInPool( - HotSpotConstantPool constantPool, int cpi) throws LinkageError { - return CTVM.resolveTypeInPool(constantPool, cpi); + public static HotSpotResolvedObjectType resolveTypeInPool( + ConstantPool constantPool, int cpi) { + return CTVM.resolveTypeInPool((HotSpotConstantPool) constantPool, cpi); } - public static HotSpotResolvedObjectTypeImpl resolveFieldInPool( - HotSpotConstantPool constantPool, int cpi, byte opcode, long[] info) { - return CTVM.resolveFieldInPool(constantPool, cpi, opcode, info); + public static HotSpotResolvedObjectType resolveFieldInPool( + ConstantPool constantPool, int cpi, byte opcode, long[] info) { + return CTVM.resolveFieldInPool((HotSpotConstantPool) constantPool, cpi, opcode, info); } public static int constantPoolRemapInstructionOperandFromCache( - HotSpotConstantPool constantPool, int cpci) { - return CTVM.constantPoolRemapInstructionOperandFromCache(constantPool, cpci); + ConstantPool constantPool, int cpci) { + return CTVM.constantPoolRemapInstructionOperandFromCache((HotSpotConstantPool) constantPool, cpci); } - public static Object lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi) { - return CTVM.lookupAppendixInPool(constantPool, cpi); + public static Object lookupAppendixInPool( + ConstantPool constantPool, int cpi) { + return CTVM.lookupAppendixInPool((HotSpotConstantPool) constantPool, cpi); } public static int installCode(TargetDescription target, - HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog) { + HotSpotCompiledCode compiledCode, InstalledCode code, HotSpotSpeculationLog speculationLog) { return CTVM.installCode(target, compiledCode, code, speculationLog); } @@ -144,10 +149,10 @@ public class CompilerToVMHelper { } public static void notifyCompilationStatistics(int id, - HotSpotResolvedJavaMethodImpl method, boolean osr, + HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode) { - CTVM.notifyCompilationStatistics(id, method, osr, processedBytecodes, + CTVM.notifyCompilationStatistics(id, (HotSpotResolvedJavaMethodImpl) method, osr, processedBytecodes, time, timeUnitsPerSecond, installedCode); } @@ -155,28 +160,28 @@ public class CompilerToVMHelper { CTVM.resetCompilationStatistics(); } - public static long initializeConfiguration() { - return CTVM.initializeConfiguration(); + public static long initializeConfiguration(HotSpotVMConfig config) { + return CTVM.initializeConfiguration(config); } - public static HotSpotResolvedJavaMethodImpl resolveMethod( - HotSpotResolvedObjectTypeImpl exactReceiver, - HotSpotResolvedJavaMethodImpl method, - HotSpotResolvedObjectTypeImpl caller) { - return CTVM.resolveMethod(exactReceiver, method, caller); + public static HotSpotResolvedJavaMethod resolveMethod( + HotSpotResolvedObjectType exactReceiver, + HotSpotResolvedJavaMethod method, + HotSpotResolvedObjectType caller) { + return CTVM.resolveMethod((HotSpotResolvedObjectTypeImpl) exactReceiver, (HotSpotResolvedJavaMethodImpl) method, (HotSpotResolvedObjectTypeImpl) caller); } - public static HotSpotResolvedJavaMethodImpl getClassInitializer( - HotSpotResolvedObjectTypeImpl type) { - return CTVM.getClassInitializer(type); + public static HotSpotResolvedJavaMethod getClassInitializer( + HotSpotResolvedObjectType type) { + return CTVM.getClassInitializer((HotSpotResolvedObjectTypeImpl) type); } - public static boolean hasFinalizableSubclass(HotSpotResolvedObjectTypeImpl type) { - return CTVM.hasFinalizableSubclass(type); + public static boolean hasFinalizableSubclass(HotSpotResolvedObjectType type) { + return CTVM.hasFinalizableSubclass((HotSpotResolvedObjectTypeImpl) type); } - public static HotSpotResolvedJavaMethodImpl getResolvedJavaMethodAtSlot(Class holder, - int slot) { + public static HotSpotResolvedJavaMethodImpl getResolvedJavaMethodAtSlot( + Class holder, int slot) { return CTVM.getResolvedJavaMethodAtSlot(holder, slot); } @@ -184,13 +189,13 @@ public class CompilerToVMHelper { return CTVM.getMaxCallTargetOffset(address); } - public static String disassembleCodeBlob(long codeBlob) { + public static String disassembleCodeBlob(InstalledCode codeBlob) { return CTVM.disassembleCodeBlob(codeBlob); } public static StackTraceElement getStackTraceElement( - HotSpotResolvedJavaMethodImpl method, int bci) { - return CTVM.getStackTraceElement(method, bci); + HotSpotResolvedJavaMethod method, int bci) { + return CTVM.getStackTraceElement((HotSpotResolvedJavaMethodImpl)method, bci); } public static Object executeInstalledCode(Object[] args, @@ -198,28 +203,28 @@ public class CompilerToVMHelper { return CTVM.executeInstalledCode(args, installedCode); } - public static long[] getLineNumberTable(HotSpotResolvedJavaMethodImpl method) { - return CTVM.getLineNumberTable(method); + public static long[] getLineNumberTable(HotSpotResolvedJavaMethod method) { + return CTVM.getLineNumberTable((HotSpotResolvedJavaMethodImpl)method); } - public static int getLocalVariableTableLength(HotSpotResolvedJavaMethodImpl method) { - return CTVM.getLocalVariableTableLength(method); + public static int getLocalVariableTableLength(HotSpotResolvedJavaMethod method) { + return CTVM.getLocalVariableTableLength((HotSpotResolvedJavaMethodImpl)method); } - public static long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method) { - return CTVM.getLocalVariableTableStart(method); + public static long getLocalVariableTableStart(HotSpotResolvedJavaMethod method) { + return CTVM.getLocalVariableTableStart((HotSpotResolvedJavaMethodImpl)method); } public static Object readUncompressedOop(long address) { return CTVM.readUncompressedOop(address); } - public static void doNotInlineOrCompile(HotSpotResolvedJavaMethodImpl method) { - CTVM.doNotInlineOrCompile(method); + public static void doNotInlineOrCompile(HotSpotResolvedJavaMethod method) { + CTVM.doNotInlineOrCompile((HotSpotResolvedJavaMethodImpl)method); } - public static void reprofile(HotSpotResolvedJavaMethodImpl method) { - CTVM.reprofile(method); + public static void reprofile(HotSpotResolvedJavaMethod method) { + CTVM.reprofile((HotSpotResolvedJavaMethodImpl)method); } public static void invalidateInstalledCode(InstalledCode installedCode) { @@ -234,14 +239,14 @@ public class CompilerToVMHelper { return CTVM.isMature(metaspaceMethodData); } - public static int allocateCompileId(HotSpotResolvedJavaMethodImpl method, + public static int allocateCompileId(HotSpotResolvedJavaMethod method, int entryBCI) { - return CTVM.allocateCompileId(method, entryBCI); + return CTVM.allocateCompileId((HotSpotResolvedJavaMethodImpl) method, entryBCI); } public static boolean hasCompiledCodeForOSR( - HotSpotResolvedJavaMethodImpl method, int entryBCI, int level) { - return CTVM.hasCompiledCodeForOSR(method, entryBCI, level); + HotSpotResolvedJavaMethod method, int entryBCI, int level) { + return CTVM.hasCompiledCodeForOSR((HotSpotResolvedJavaMethodImpl) method, entryBCI, level); } public static String getSymbol(long metaspaceSymbol) { @@ -250,7 +255,7 @@ public class CompilerToVMHelper { public static HotSpotStackFrameReference getNextStackFrame( HotSpotStackFrameReference frame, - HotSpotResolvedJavaMethodImpl[] methods, int initialSkip) { + ResolvedJavaMethod[] methods, int initialSkip) { return CTVM.getNextStackFrame(frame, methods, initialSkip); } @@ -259,9 +264,9 @@ public class CompilerToVMHelper { CTVM.materializeVirtualObjects(stackFrame, invalidate); } - public static int getVtableIndexForInterfaceMethod(HotSpotResolvedObjectTypeImpl type, - HotSpotResolvedJavaMethodImpl method) { - return CTVM.getVtableIndexForInterfaceMethod(type, method); + public static int getVtableIndexForInterfaceMethod(HotSpotResolvedObjectType type, + HotSpotResolvedJavaMethod method) { + return CTVM.getVtableIndexForInterfaceMethod((HotSpotResolvedObjectTypeImpl) type, (HotSpotResolvedJavaMethodImpl) method); } public static boolean shouldDebugNonSafepoints() { @@ -276,7 +281,7 @@ public class CompilerToVMHelper { CTVM.flushDebugOutput(); } - public static HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base, + public static HotSpotResolvedJavaMethod getResolvedJavaMethod(Object base, long displacement) { return CTVM.getResolvedJavaMethod(base, displacement); } @@ -285,8 +290,24 @@ public class CompilerToVMHelper { return CTVM.getConstantPool(base, displacement); } - public static HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, + public static HotSpotResolvedObjectType getResolvedJavaType(Object base, long displacement, boolean compressed) { return CTVM.getResolvedJavaType(base, displacement, compressed); } + + public static long getMetaspacePointer(Object o) { + return ((MetaspaceWrapperObject) o).getMetaspacePointer(); + } + + public static Class CompilerToVMClass() { + return CompilerToVM.class; + } + + public static Class HotSpotConstantPoolClass() { + return HotSpotConstantPool.class; + } + + public static Class getMirror(HotSpotResolvedObjectType type) { + return ((HotSpotResolvedJavaType) type).mirror(); + } } diff --git a/hotspot/test/compiler/jvmci/common/JVMCIHelpers.java b/hotspot/test/compiler/jvmci/common/JVMCIHelpers.java index 9b80bf809d5..35cece6db07 100644 --- a/hotspot/test/compiler/jvmci/common/JVMCIHelpers.java +++ b/hotspot/test/compiler/jvmci/common/JVMCIHelpers.java @@ -24,10 +24,11 @@ package compiler.jvmci.common; import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.hotspot.HotSpotVMEventListener; -import jdk.vm.ci.compiler.Compiler; -import jdk.vm.ci.compiler.CompilerFactory; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.runtime.JVMCICompiler; +import jdk.vm.ci.runtime.JVMCICompilerFactory; import jdk.vm.ci.runtime.JVMCIRuntime; /* @@ -39,16 +40,15 @@ public class JVMCIHelpers { // just empty, using default interface methods } - public static class EmptyHotspotCompiler implements Compiler { + public static class EmptyHotspotCompiler implements JVMCICompiler { @Override - public void compileMethod(ResolvedJavaMethod method, int entryBCI, - long jvmciEnv, int id) { + public void compileMethod(CompilationRequest request) { // do nothing } } - public static class EmptyCompilerFactory implements CompilerFactory { + public static class EmptyCompilerFactory implements JVMCICompilerFactory { @Override public String getCompilerName() { @@ -56,12 +56,7 @@ public class JVMCIHelpers { } @Override - public Architecture initializeArchitecture(Architecture arch) { - return arch; - } - - @Override - public Compiler createCompiler(JVMCIRuntime runtime) { + public JVMCICompiler createCompiler(JVMCIRuntime runtime) { return new EmptyHotspotCompiler(); } } diff --git a/hotspot/test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java b/hotspot/test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java new file mode 100644 index 00000000000..4a49d01aca4 --- /dev/null +++ b/hotspot/test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015, 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.vm.ci.hotspot; + +/** + * A public available version of MetaspaceWrapperObject interface. + */ +public interface PublicMetaspaceWrapperObject extends MetaspaceWrapperObject { } diff --git a/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.Compiler b/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.runtime.JVMCICompiler similarity index 100% rename from hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.Compiler rename to hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.runtime.JVMCICompiler diff --git a/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.CompilerFactory b/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.runtime.JVMCICompilerFactory similarity index 100% rename from hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.CompilerFactory rename to hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.runtime.JVMCICompilerFactory diff --git a/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java b/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java index eb09de4fdc0..7d36796ecaf 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -34,6 +34,7 @@ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. * -XX:-BackgroundCompilation + -XX:+LogCompilation * compiler.jvmci.compilerToVM.AllocateCompileIdTest */ @@ -51,7 +52,7 @@ import java.util.HashSet; import compiler.jvmci.common.testcases.TestCase; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.test.lib.Asserts; import jdk.test.lib.Pair; import jdk.test.lib.Utils; @@ -74,8 +75,9 @@ public class AllocateCompileIdTest { try { Class aClass = DummyClass.class; Method method = aClass.getMethod("withLoop"); - result.add(new CompileCodeTestCase(method, 17)); - result.add(new CompileCodeTestCase(method, -1)); + Object receiver = new DummyClass(); + result.add(new CompileCodeTestCase(receiver, method, 17)); + result.add(new CompileCodeTestCase(receiver, method, -1)); } catch (NoSuchMethodException e) { throw new Error("TEST BUG : " + e, e); } @@ -90,16 +92,19 @@ public class AllocateCompileIdTest { try { Class aClass = DummyClass.class; + Object receiver = new DummyClass(); Method method = aClass.getMethod("dummyInstanceFunction"); // greater than bytecode.length int[] bcis = new int[] {30, 50, 200}; for (int bci : bcis) { - result.add(new Pair<>(new CompileCodeTestCase(method, bci), + result.add(new Pair<>( + new CompileCodeTestCase(receiver, method, bci), IllegalArgumentException.class)); } bcis = new int[] {-4, -50, -200}; for (int bci : bcis) { - result.add(new Pair<>(new CompileCodeTestCase(method, bci), + result.add(new Pair<>( + new CompileCodeTestCase(receiver, method, bci), IllegalArgumentException.class)); } } catch (NoSuchMethodException e) { @@ -111,8 +116,10 @@ public class AllocateCompileIdTest { private void runSanityCorrectTest(CompileCodeTestCase testCase) { System.out.println(testCase); Executable aMethod = testCase.executable; + // to generate ciTypeFlow + System.out.println(testCase.invoke(Utils.getNullValues(aMethod.getParameterTypes()))); int bci = testCase.bci; - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); int wbCompileID = getWBCompileID(testCase); int id = CompilerToVMHelper.allocateCompileId(method, bci); @@ -140,7 +147,7 @@ public class AllocateCompileIdTest { Class exception = testCase.second; Executable aMethod = testCase.first.executable; int bci = testCase.first.bci; - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); Utils.runAndCheckException( () -> CompilerToVMHelper.allocateCompileId(method, bci), diff --git a/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java index 9b164dade4e..8bfd63b9193 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -45,7 +45,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.test.lib.Asserts; import sun.hotspot.WhiteBox; @@ -59,7 +59,7 @@ public class CanInlineMethodTest { } private static void runSanityTest(Executable aMethod) { - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); boolean canInline = CompilerToVMHelper.canInlineMethod(method); boolean expectedCanInline = !WB.testSetDontInlineMethod(aMethod, diff --git a/hotspot/test/compiler/jvmci/compilerToVM/CollectCountersTest.java b/hotspot/test/compiler/jvmci/compilerToVM/CollectCountersTest.java index be23e77ff2e..e77e06c80ab 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/CollectCountersTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/CollectCountersTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib/ + * @library / /testlibrary /test/lib/ * @compile ../common/CompilerToVMHelper.java * @run main ClassFileInstaller * jdk.vm.ci.hotspot.CompilerToVMHelper diff --git a/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java b/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java index 00be80ea3ab..fa6483cf449 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java @@ -24,12 +24,17 @@ package compiler.jvmci.compilerToVM; +import compiler.jvmci.common.CTVMUtilities; import compiler.testlibrary.CompilerUtils; import jdk.test.lib.Utils; +import jdk.vm.ci.code.InstalledCode; import sun.hotspot.WhiteBox; import sun.hotspot.code.NMethod; import java.lang.reflect.Executable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; @@ -37,12 +42,12 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import jdk.test.lib.Pair; /** * A test case for tests which require compiled code. */ -public final class CompileCodeTestCase { - public static final Map, Object> RECEIVERS; +public class CompileCodeTestCase { private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final int COMP_LEVEL; static { @@ -56,21 +61,51 @@ public final class CompileCodeTestCase { Interface.class, Dummy.class, DummyEx.class}; + private static final Map, Object> RECEIVERS; + public final Object receiver; public final Executable executable; public final int bci; private final boolean isOsr; - public CompileCodeTestCase(Executable executable, int bci) { + public CompileCodeTestCase(Object receiver, Executable executable, + int bci) { + this.receiver = receiver; this.executable = executable; this.bci = bci; - isOsr = bci >= 0; + isOsr = (bci >= 0); } public NMethod compile() { return compile(COMP_LEVEL); } + public Pair invoke(Object[] args) { + boolean old = executable.isAccessible(); + executable.setAccessible(true); + try { + try { + if (executable instanceof Method) { + Method m = (Method) executable; + return new Pair<>(m.invoke(receiver, args), null); + } + + if (executable instanceof Constructor) { + Constructor c = (Constructor) executable; + return new Pair<>(c.newInstance(args), null); + } + } catch (InvocationTargetException e) { + return new Pair<>(null, e.getCause()); + } catch (Throwable e) { + return new Pair<>(null, e); + } + } finally { + executable.setAccessible(old); + } + throw new Error(executable + " has unsupported type " + + executable.getClass()); + } + public NMethod compile(int level) { boolean enqueued = WB.enqueueMethodForCompilation(executable, level, bci); @@ -86,13 +121,17 @@ public final class CompileCodeTestCase { public static List generate(int bci) { ArrayList result = new ArrayList<>(); for (Class aClass : CLASSES) { + Object receiver = RECEIVERS.get(aClass); + if (receiver == null) { + throw new Error("TESTBUG : no receiver for class " + aClass); + } for (Executable m : aClass.getDeclaredConstructors()) { - result.add(new CompileCodeTestCase(m, bci)); + result.add(new CompileCodeTestCase(receiver, m, bci)); } Arrays.stream(aClass.getDeclaredMethods()) .filter(m -> !Modifier.isAbstract(m.getModifiers())) .filter(m -> !Modifier.isNative(m.getModifiers())) - .map(m -> new CompileCodeTestCase(m, bci)) + .map(m -> new CompileCodeTestCase(receiver, m, bci)) .forEach(result::add); } return result; @@ -102,6 +141,14 @@ public final class CompileCodeTestCase { return NMethod.get(executable, isOsr); } + public InstalledCode toInstalledCode() { + NMethod nmethod = toNMethod(); + long address = nmethod == null ? 0L : nmethod.address; + long entryPoint = nmethod == null ? 0L : nmethod.entry_point; + return CTVMUtilities.getInstalledCode( + executable.getName(), address, entryPoint); + } + @Override public String toString() { return "CompileCodeTestCase{" + diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java index 9f5409e551d..b9716cca2a2 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java @@ -26,8 +26,7 @@ package compiler.jvmci.compilerToVM; import java.util.HashMap; import java.util.Map; -import jdk.vm.ci.hotspot.HotSpotConstantPool; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.internal.misc.SharedSecrets; import sun.reflect.ConstantPool; @@ -35,15 +34,15 @@ import sun.reflect.ConstantPool; * Common class for jdk.vm.ci.hotspot.CompilerToVM constant pool tests */ public class ConstantPoolTestCase { - private final Map typeTests; public static interface Validator { - void validate(HotSpotConstantPool constantPoolCTVM, ConstantPool constantPoolSS, + void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM, + ConstantPool constantPoolSS, ConstantPoolTestsHelper.DummyClasses dummyClass, int index); } - public ConstantPoolTestCase(Map typeTests) { + public ConstantPoolTestCase(Map typeTests) { this.typeTests = new HashMap<>(); this.typeTests.putAll(typeTests); } @@ -120,9 +119,10 @@ public class ConstantPoolTestCase { for (ConstantPoolTestsHelper.DummyClasses dummyClass : ConstantPoolTestsHelper.DummyClasses.values()) { System.out.printf("%nTesting dummy %s%n", dummyClass.klass); - HotSpotResolvedObjectTypeImpl holder = HotSpotResolvedObjectTypeImpl + HotSpotResolvedObjectType holder = HotSpotResolvedObjectType .fromObjectClass(dummyClass.klass); - HotSpotConstantPool constantPoolCTVM = holder.getConstantPool(); + jdk.vm.ci.meta.ConstantPool constantPoolCTVM + = holder.getConstantPool(); ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess(). getConstantPool(dummyClass.klass); for (Integer i : dummyClass.cp.keySet()) { diff --git a/hotspot/test/compiler/jvmci/compilerToVM/DebugOutputTest.java b/hotspot/test/compiler/jvmci/compilerToVM/DebugOutputTest.java index 31d4ac0a293..2f0bc449986 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/DebugOutputTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/DebugOutputTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java * @run main ClassFileInstaller * jdk.vm.ci.hotspot.CompilerToVMHelper diff --git a/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java index 10ab70bc5d2..0d4ad698738 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @ignore 8139700 * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox @@ -42,10 +42,12 @@ package compiler.jvmci.compilerToVM; import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.code.InstalledCode; import jdk.test.lib.Asserts; import sun.hotspot.code.NMethod; import java.util.List; +import jdk.test.lib.Utils; public class DisassembleCodeBlobTest { @@ -56,12 +58,23 @@ public class DisassembleCodeBlobTest { = CompileCodeTestCase.generate(/* bci = */ -1); testCases.addAll(CompileCodeTestCase.generate(/* bci = */ 0)); testCases.forEach(test::check); + testCases.stream().findAny().ifPresent(test::checkZero); test.checkNull(); } private void checkNull() { - String str = CompilerToVMHelper.disassembleCodeBlob(0L); - Asserts.assertNull(str, "not null string returned for null pointer"); + Utils.runAndCheckException( + () -> CompilerToVMHelper.disassembleCodeBlob(null), + NullPointerException.class); + } + + private void checkZero(CompileCodeTestCase testCase) { + System.out.println("checkZero for " + testCase); + testCase.deoptimize(); + InstalledCode installedCode = testCase.toInstalledCode(); + String str = CompilerToVMHelper.disassembleCodeBlob(installedCode); + Asserts.assertNull(str, testCase + + " : non-null return value for invalid installCode"); } private void check(CompileCodeTestCase testCase) { @@ -71,12 +84,13 @@ public class DisassembleCodeBlobTest { if (nMethod == null) { throw new Error(testCase + " : method is not compiled"); } - String str = CompilerToVMHelper.disassembleCodeBlob(nMethod.address); + InstalledCode installedCode = testCase.toInstalledCode(); + String str = CompilerToVMHelper.disassembleCodeBlob(installedCode); if (str != null) { Asserts.assertGT(str.length(), 0, testCase + " : returned string has to be non-zero length"); } - String str2 = CompilerToVMHelper.disassembleCodeBlob(nMethod.address); + String str2 = CompilerToVMHelper.disassembleCodeBlob(installedCode); Asserts.assertEQ(str, str2, testCase + " : 2nd invocation returned different value"); } diff --git a/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java b/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java index b3f513c73de..de8d74aa001 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -45,7 +45,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.test.lib.Asserts; import sun.hotspot.WhiteBox; @@ -59,7 +59,7 @@ public class DoNotInlineOrCompileTest { } private static void runSanityTest(Executable aMethod) { - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); boolean canInline = CompilerToVMHelper.canInlineMethod(method); Asserts.assertTrue(canInline, "Unexpected initial " + diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java index 6e64d079370..10f387db30c 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java @@ -4,6 +4,7 @@ import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; import jdk.test.lib.Pair; import sun.hotspot.code.NMethod; @@ -21,7 +22,7 @@ import java.util.Map; * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox * compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest @@ -35,7 +36,6 @@ import java.util.Map; public class ExecuteInstalledCodeTest { - public static void main(String[] args) { ExecuteInstalledCodeTest test = new ExecuteInstalledCodeTest(); List testCases = new ArrayList<>(); @@ -54,15 +54,14 @@ public class ExecuteInstalledCodeTest { // to have a clean state testCase.deoptimize(); Pair reflectionResult; - Object[] args = getArguments(testCase.executable); - reflectionResult = invoke(testCase, args); + Object[] args = Utils.getNullValues( + testCase.executable.getParameterTypes()); + reflectionResult = testCase.invoke(args); NMethod nMethod = testCase.compile(); if (nMethod == null) { throw new Error(testCase + " : nmethod is null"); } - InstalledCode installedCode = new InstalledCode( - testCase.executable.getName()); - installedCode.setAddress(nMethod.address); + InstalledCode installedCode = testCase.toInstalledCode(); Object result = null; Throwable expectedException = reflectionResult.second; boolean gotException = true; @@ -107,70 +106,10 @@ public class ExecuteInstalledCodeTest { if (!Modifier.isStatic(testCase.executable.getModifiers())) { // add instance as 0th arg Object[] newArgs = new Object[args.length + 1]; - newArgs[0] = getReciever(testCase); + newArgs[0] = testCase.receiver; System.arraycopy(args, 0, newArgs, 1, args.length); args = newArgs; } return args; } - - private Object getReciever(CompileCodeTestCase testCase) { - return CompileCodeTestCase.RECEIVERS.get( - testCase.executable.getDeclaringClass()); - } - - public Pair invoke( - CompileCodeTestCase testCase, Object[] args) { - Executable executable = testCase.executable; - boolean old = executable.isAccessible(); - executable.setAccessible(true); - try { - try { - if (executable instanceof Method) { - Method m = (Method) executable; - return new Pair<>(m.invoke(getReciever(testCase), args), null); - } - - if (executable instanceof Constructor) { - Constructor c = (Constructor) executable; - return new Pair<>(c.newInstance(args), null); - } - } catch (InvocationTargetException e) { - return new Pair<>(null, e.getCause()); - } catch (Throwable e) { - return new Pair<>(null, e); - } - } finally { - executable.setAccessible(old); - } - throw new Error(executable + " has unsupported type " - + executable.getClass()); - } - - private Object[] getArguments(Executable method) { - Class[] params = method.getParameterTypes(); - Object[] result = new Object[params.length]; - int i = 0; - for (Class aClass : params) { - result[i++] = getArgument(aClass); - } - return result; - } - private static Map, Object> DEFAULT_VALUES = new HashMap<>(); - static { - DEFAULT_VALUES.put(boolean.class, false); - DEFAULT_VALUES.put(byte.class, (byte) 0); - DEFAULT_VALUES.put(short.class, (short) 0); - DEFAULT_VALUES.put(char.class, '\0'); - DEFAULT_VALUES.put(int.class, 0); - DEFAULT_VALUES.put(long.class, 0L); - DEFAULT_VALUES.put(float.class, 0.0f); - DEFAULT_VALUES.put(double.class, 0.0d); - } - private Object getArgument(Class aClass) { - if (aClass.isPrimitive()) { - return DEFAULT_VALUES.get(aClass); - } - return null; - } } diff --git a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java index 15ae1b74212..6405289a2a9 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.FindUniqueConcreteMethodTest * @run main ClassFileInstaller @@ -45,8 +45,8 @@ import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; @@ -97,26 +97,26 @@ public class FindUniqueConcreteMethodTest { private void runTest(TestCase tcase) throws NoSuchMethodException { System.out.println(tcase); Method method = tcase.holder.getDeclaredMethod(tcase.methodName); - HotSpotResolvedJavaMethodImpl testMethod = CTVMUtilities - .getResolvedMethod(tcase.reciever, method); - HotSpotResolvedObjectTypeImpl resolvedType = CompilerToVMHelper - .lookupType(Utils.toJVMTypeSignature(tcase.reciever), getClass(), + HotSpotResolvedJavaMethod testMethod = CTVMUtilities + .getResolvedMethod(tcase.receiver, method); + HotSpotResolvedObjectType resolvedType = CompilerToVMHelper + .lookupType(Utils.toJVMTypeSignature(tcase.receiver), getClass(), /* resolve = */ true); - HotSpotResolvedJavaMethodImpl concreteMethod = CompilerToVMHelper + HotSpotResolvedJavaMethod concreteMethod = CompilerToVMHelper .findUniqueConcreteMethod(resolvedType, testMethod); Asserts.assertEQ(concreteMethod, tcase.isPositive ? testMethod : null, "Unexpected concrete method for " + tcase.methodName); } private static class TestCase { - public final Class reciever; + public final Class receiver; public final Class holder; public final String methodName; public final boolean isPositive; public TestCase(boolean isPositive, Class clazz, Class holder, String methodName) { - this.reciever = clazz; + this.receiver = clazz; this.methodName = methodName; this.isPositive = isPositive; this.holder = holder; @@ -124,8 +124,8 @@ public class FindUniqueConcreteMethodTest { @Override public String toString() { - return String.format("CASE: reciever=%s, holder=%s, method=%s," - + " isPositive=%s", reciever.getName(), + return String.format("CASE: receiver=%s, holder=%s, method=%s," + + " isPositive=%s", receiver.getName(), holder.getName(), methodName, isPositive); } } diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java index b3c16002580..1765f1ec367 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI @@ -40,7 +40,7 @@ import compiler.jvmci.common.CTVMUtilities; import compiler.jvmci.common.testcases.TestCase; import java.lang.reflect.Executable; import java.lang.reflect.Modifier; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.test.lib.Asserts; @@ -53,7 +53,7 @@ public class GetBytecodeTest { } private static void runSanityTest(Executable aMethod) { - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); byte[] bytecode = CompilerToVMHelper.getBytecode(method); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java index 6525b115ddd..d0a6097c035 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.GetClassInitializerTest * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper @@ -44,8 +44,8 @@ import compiler.jvmci.common.testcases.SingleImplementerInterface; import java.util.HashSet; import java.util.Set; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; @@ -78,10 +78,10 @@ public class GetClassInitializerTest { private void runTest(TestCase tcase) { System.out.println(tcase); String className = tcase.holder.getName(); - HotSpotResolvedObjectTypeImpl resolvedClazz = CompilerToVMHelper + HotSpotResolvedObjectType resolvedClazz = CompilerToVMHelper .lookupType(Utils.toJVMTypeSignature(tcase.holder), getClass(), /* resolve = */ true); - HotSpotResolvedJavaMethodImpl initializer = CompilerToVMHelper + HotSpotResolvedJavaMethod initializer = CompilerToVMHelper .getClassInitializer(resolvedClazz); if (tcase.isPositive) { Asserts.assertNotNull(initializer, "Couldn't get initializer for " diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java index 68185a9b06b..ae541842b6a 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java @@ -26,13 +26,14 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / - * @compile ../common/CompilerToVMHelper.java + * @library /testlibrary /test/lib / + * @compile ../common/CompilerToVMHelper.java ../common/PublicMetaspaceWrapperObject.java * @build sun.hotspot.WhiteBox * compiler.jvmci.compilerToVM.GetConstantPoolTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * jdk.vm.ci.hotspot.CompilerToVMHelper + * jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetConstantPoolTest @@ -40,11 +41,11 @@ package compiler.jvmci.compilerToVM; import java.lang.reflect.Field; +import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotConstantPool; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; -import jdk.vm.ci.hotspot.MetaspaceWrapperObject; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject; import jdk.test.lib.Utils; import sun.hotspot.WhiteBox; import sun.misc.Unsafe; @@ -56,25 +57,26 @@ public class GetConstantPoolTest { private static enum TestCase { NULL_BASE { @Override - HotSpotConstantPool getConstantPool() { + ConstantPool getConstantPool() { return CompilerToVMHelper.getConstantPool(null, getPtrToCpAddress()); } }, JAVA_METHOD_BASE { @Override - HotSpotConstantPool getConstantPool() { - HotSpotResolvedJavaMethodImpl methodInstance + ConstantPool getConstantPool() { + HotSpotResolvedJavaMethod methodInstance = CompilerToVMHelper.getResolvedJavaMethodAtSlot( TEST_CLASS, 0); Field field; try { - field = HotSpotResolvedJavaMethodImpl - .class.getDeclaredField("metaspaceMethod"); + // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod + field = methodInstance.getClass() + .getDeclaredField("metaspaceMethod"); field.setAccessible(true); field.set(methodInstance, getPtrToCpAddress()); } catch (ReflectiveOperationException e) { - throw new Error("TESTBUG : " + e.getMessage(), e); + throw new Error("TESTBUG : " + e, e); } return CompilerToVMHelper.getConstantPool(methodInstance, 0L); @@ -82,12 +84,12 @@ public class GetConstantPoolTest { }, CONSTANT_POOL_BASE { @Override - HotSpotConstantPool getConstantPool() { - HotSpotConstantPool cpInst; + ConstantPool getConstantPool() { + ConstantPool cpInst; try { cpInst = CompilerToVMHelper.getConstantPool(null, getPtrToCpAddress()); - Field field = HotSpotConstantPool.class + Field field = CompilerToVMHelper.HotSpotConstantPoolClass() .getDeclaredField("metaspaceConstantPool"); field.setAccessible(true); field.set(cpInst, getPtrToCpAddress()); @@ -99,12 +101,12 @@ public class GetConstantPoolTest { }, CONSTANT_POOL_BASE_IN_TWO { @Override - HotSpotConstantPool getConstantPool() { + ConstantPool getConstantPool() { long ptr = getPtrToCpAddress(); - HotSpotConstantPool cpInst; + ConstantPool cpInst; try { cpInst = CompilerToVMHelper.getConstantPool(null, ptr); - Field field = HotSpotConstantPool.class + Field field = CompilerToVMHelper.HotSpotConstantPoolClass() .getDeclaredField("metaspaceConstantPool"); field.setAccessible(true); field.set(cpInst, ptr / 2L); @@ -117,12 +119,12 @@ public class GetConstantPoolTest { }, CONSTANT_POOL_BASE_ZERO { @Override - HotSpotConstantPool getConstantPool() { + ConstantPool getConstantPool() { long ptr = getPtrToCpAddress(); - HotSpotConstantPool cpInst; + ConstantPool cpInst; try { cpInst = CompilerToVMHelper.getConstantPool(null, ptr); - Field field = HotSpotConstantPool.class + Field field = CompilerToVMHelper.HotSpotConstantPoolClass() .getDeclaredField("metaspaceConstantPool"); field.setAccessible(true); field.set(cpInst, 0L); @@ -134,9 +136,9 @@ public class GetConstantPoolTest { }, OBJECT_TYPE_BASE { @Override - HotSpotConstantPool getConstantPool() { - HotSpotResolvedObjectTypeImpl type - = HotSpotResolvedObjectTypeImpl.fromObjectClass( + ConstantPool getConstantPool() { + HotSpotResolvedObjectType type + = HotSpotResolvedObjectType.fromObjectClass( OBJECT_TYPE_BASE.getClass()); long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE); return CompilerToVMHelper.getConstantPool(type, @@ -144,26 +146,28 @@ public class GetConstantPoolTest { } }, ; - abstract HotSpotConstantPool getConstantPool(); + abstract ConstantPool getConstantPool(); } private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Class TEST_CLASS = GetConstantPoolTest.class; private static final long CP_ADDRESS = WB.getConstantPool(GetConstantPoolTest.class); public void test(TestCase testCase) { System.out.println(testCase.name()); - HotSpotConstantPool cp = testCase.getConstantPool(); + ConstantPool cp = testCase.getConstantPool(); String cpStringRep = cp.toString(); - if (!cpStringRep.contains(HotSpotConstantPool.class.getSimpleName()) + String cpClassSimpleName + = CompilerToVMHelper.HotSpotConstantPoolClass().getSimpleName(); + if (!cpStringRep.contains(cpClassSimpleName) || !cpStringRep.contains(TEST_CLASS.getName())) { String msg = String.format("%s : " + " Constant pool is not valid." + " String representation should contain \"%s\" and \"%s\"", - testCase.name(), - HotSpotConstantPool.class.getSimpleName(), + testCase.name(), cpClassSimpleName, TEST_CLASS.getName()); throw new AssertionError(msg); } @@ -180,8 +184,7 @@ public class GetConstantPoolTest { private static void testObjectBase() { try { - HotSpotConstantPool cp - = CompilerToVMHelper.getConstantPool(new Object(), 0L); + Object cp = CompilerToVMHelper.getConstantPool(new Object(), 0L); throw new AssertionError("Test OBJECT_BASE." + " Expected IllegalArgumentException has not been caught"); } catch (IllegalArgumentException iae) { @@ -190,8 +193,8 @@ public class GetConstantPoolTest { } private static void testMetaspaceWrapperBase() { try { - HotSpotConstantPool cp = CompilerToVMHelper.getConstantPool( - new MetaspaceWrapperObject() { + Object cp = CompilerToVMHelper.getConstantPool( + new PublicMetaspaceWrapperObject() { @Override public long getMetaspacePointer() { return getPtrToCpAddress(); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java index 9d928d3d045..2793286ae17 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI @@ -42,7 +42,7 @@ import java.lang.reflect.Executable; import java.net.Socket; import java.util.HashMap; import java.util.Map; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; @@ -76,7 +76,7 @@ public class GetExceptionTableTest { private static void runSanityTest(Executable aMethod, Integer expectedTableLength) { - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); int tableLength = CompilerToVMHelper.getExceptionTableLength(method); Asserts.assertEQ(tableLength, expectedTableLength, aMethod diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java index aab452fd58a..8055d470330 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib/ + * @library / /testlibrary /test/lib/ * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.GetImplementorTest * @run main ClassFileInstaller @@ -51,7 +51,7 @@ import java.util.HashSet; import java.util.Set; import java.util.stream.Stream; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; @@ -98,12 +98,12 @@ public class GetImplementorTest { private void runTest(TestCase tcase) { System.out.println(tcase); - HotSpotResolvedObjectTypeImpl resolvedIface = CompilerToVMHelper + HotSpotResolvedObjectType resolvedIface = CompilerToVMHelper .lookupType(Utils.toJVMTypeSignature(tcase.anInterface), getClass(), /* resolve = */ true); - HotSpotResolvedObjectTypeImpl resolvedImplementer = CompilerToVMHelper + HotSpotResolvedObjectType resolvedImplementer = CompilerToVMHelper .getImplementor(resolvedIface); - HotSpotResolvedObjectTypeImpl resolvedExpected = null; + HotSpotResolvedObjectType resolvedExpected = null; if (tcase.expectedImplementer != null) { resolvedExpected = CompilerToVMHelper.lookupType(Utils .toJVMTypeSignature(tcase.expectedImplementer), diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java index 1b3dcdcd60d..c609d017cc8 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI @@ -39,7 +39,7 @@ package compiler.jvmci.compilerToVM; import compiler.jvmci.common.CTVMUtilities; import compiler.jvmci.common.testcases.TestCase; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassWriter; @@ -67,7 +67,7 @@ public class GetLineNumberTableTest { } public static void runSanityTest(Executable aMethod) { - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); long[] lineNumbers = CompilerToVMHelper.getLineNumberTable(method); long[] expectedLineNumbers = getExpectedLineNumbers(aMethod); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java index 9bdb8525414..d83f87b56c0 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @clean compiler.jvmci.compilerToVM.* * @compile -g DummyInterface.java * @compile -g DummyAbstractClass.java @@ -42,7 +42,7 @@ package compiler.jvmci.compilerToVM; import compiler.jvmci.common.CTVMUtilities; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; @@ -100,7 +100,7 @@ public class GetLocalVariableTableTest { private static void runSanityTest(Executable aMethod, Integer expectedTableLength) { - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); int tblLength = CompilerToVMHelper.getLocalVariableTableLength(method); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java index e18581ee6d4..74c2481e6bd 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib/ + * @library / /testlibrary /test/lib/ * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.GetMaxCallTargetOffsetTest * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java index 4a7e3fa7adb..063653b1d25 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java * @run main ClassFileInstaller * jdk.vm.ci.hotspot.CompilerToVMHelper @@ -37,20 +37,19 @@ package compiler.jvmci.compilerToVM; import compiler.jvmci.common.CTVMUtilities; import java.lang.reflect.Method; -import jdk.vm.ci.hotspot.CompilerToVM; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; import jdk.vm.ci.hotspot.HotSpotStackFrameReference; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.test.lib.Asserts; public class GetNextStackFrameTest { private static final int RECURSION_AMOUNT = 3; - private static final HotSpotResolvedJavaMethodImpl REC_FRAME_METHOD; - private static final HotSpotResolvedJavaMethodImpl FRAME1_METHOD; - private static final HotSpotResolvedJavaMethodImpl FRAME2_METHOD; - private static final HotSpotResolvedJavaMethodImpl FRAME3_METHOD; - private static final HotSpotResolvedJavaMethodImpl FRAME4_METHOD; - private static final HotSpotResolvedJavaMethodImpl RUN_METHOD; + private static final ResolvedJavaMethod REC_FRAME_METHOD; + private static final ResolvedJavaMethod FRAME1_METHOD; + private static final ResolvedJavaMethod FRAME2_METHOD; + private static final ResolvedJavaMethod FRAME3_METHOD; + private static final ResolvedJavaMethod FRAME4_METHOD; + private static final ResolvedJavaMethod RUN_METHOD; static { Method method; @@ -69,7 +68,7 @@ public class GetNextStackFrameTest { method = Thread.class.getDeclaredMethod("run"); RUN_METHOD = CTVMUtilities.getResolvedMethod(Thread.class, method); } catch (NoSuchMethodException e) { - throw new Error("TEST BUG: can't find a test method", e); + throw new Error("TEST BUG: can't find a test method : " + e, e); } } @@ -126,7 +125,7 @@ public class GetNextStackFrameTest { */ private void findFirst() { checkNextFrameFor(null /* topmost frame */, - new HotSpotResolvedJavaMethodImpl[] + new ResolvedJavaMethod[] {FRAME2_METHOD, FRAME3_METHOD, FRAME4_METHOD}, FRAME4_METHOD, 0); } @@ -139,26 +138,26 @@ public class GetNextStackFrameTest { // Check that we would get a frame 4 starting from the topmost frame HotSpotStackFrameReference nextStackFrame = checkNextFrameFor( null /* topmost frame */, - new HotSpotResolvedJavaMethodImpl[] {FRAME4_METHOD}, + new ResolvedJavaMethod[] {FRAME4_METHOD}, FRAME4_METHOD, 0); // Check that we would get a frame 3 starting from frame 4 when we try // to search one of the next two frames nextStackFrame = checkNextFrameFor(nextStackFrame, - new HotSpotResolvedJavaMethodImpl[] {FRAME3_METHOD, + new ResolvedJavaMethod[] {FRAME3_METHOD, FRAME2_METHOD}, FRAME3_METHOD, 0); // Check that we would get a frame 1 nextStackFrame = checkNextFrameFor(nextStackFrame, - new HotSpotResolvedJavaMethodImpl[] {FRAME1_METHOD}, + new ResolvedJavaMethod[] {FRAME1_METHOD}, FRAME1_METHOD, 0); // Check that we would skip (RECURSION_AMOUNT - 1) methods and find a // recursionFrame starting from frame 1 nextStackFrame = checkNextFrameFor(nextStackFrame, - new HotSpotResolvedJavaMethodImpl[] {REC_FRAME_METHOD}, + new ResolvedJavaMethod[] {REC_FRAME_METHOD}, REC_FRAME_METHOD, RECURSION_AMOUNT - 1); // Check that we would get a Thread::run method frame; nextStackFrame = checkNextFrameFor(nextStackFrame, - new HotSpotResolvedJavaMethodImpl[] {RUN_METHOD}, + new ResolvedJavaMethod[] {RUN_METHOD}, RUN_METHOD, 0); // Check that there are no more frames after thread's run method nextStackFrame = CompilerToVMHelper.getNextStackFrame(nextStackFrame, @@ -187,7 +186,7 @@ public class GetNextStackFrameTest { // Get frame 4 HotSpotStackFrameReference nextStackFrame = CompilerToVMHelper .getNextStackFrame(null /* topmost frame */, - new HotSpotResolvedJavaMethodImpl[] {FRAME4_METHOD}, 0); + new ResolvedJavaMethod[] {FRAME4_METHOD}, 0); // Get frame 2 by skipping one method starting from frame 4 checkNextFrameFor(nextStackFrame, null /* any */, FRAME2_METHOD , 1 /* skip one */); @@ -198,15 +197,18 @@ public class GetNextStackFrameTest { */ private void findYourself() { Method method; + Class aClass = CompilerToVMHelper.CompilerToVMClass(); try { - method = CompilerToVM.class.getDeclaredMethod("getNextStackFrame", - HotSpotStackFrameReference.class, - HotSpotResolvedJavaMethodImpl[].class, int.class); + method = aClass.getDeclaredMethod( + "getNextStackFrame", + HotSpotStackFrameReference.class, + ResolvedJavaMethod[].class, + int.class); } catch (NoSuchMethodException e) { - throw new Error("TEST BUG: can't find getNextStackFrame method"); + throw new Error("TEST BUG: can't find getNextStackFrame : " + e, e); } - HotSpotResolvedJavaMethodImpl self - = CTVMUtilities.getResolvedMethod(CompilerToVM.class, method); + ResolvedJavaMethod self + = CTVMUtilities.getResolvedMethod(aClass, method); checkNextFrameFor(null /* topmost frame */, null /* any */, self, 0); } @@ -221,8 +223,8 @@ public class GetNextStackFrameTest { */ private HotSpotStackFrameReference checkNextFrameFor( HotSpotStackFrameReference currentFrame, - HotSpotResolvedJavaMethodImpl[] searchMethods, - HotSpotResolvedJavaMethodImpl expected, + ResolvedJavaMethod[] searchMethods, + ResolvedJavaMethod expected, int skip) { HotSpotStackFrameReference nextStackFrame = CompilerToVMHelper .getNextStackFrame(currentFrame, searchMethods, skip); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java index db8d0c6fc25..a235e683440 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI @@ -36,7 +36,7 @@ package compiler.jvmci.compilerToVM; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; import java.util.HashMap; @@ -94,7 +94,7 @@ public class GetResolvedJavaMethodAtSlotTest { } private static void testSlotBigger(Class holder) { - HotSpotResolvedJavaMethodImpl method + HotSpotResolvedJavaMethod method = CompilerToVMHelper.getResolvedJavaMethodAtSlot(holder, 50); Asserts.assertNull(method, "Got method for non existing slot 50 in " + holder); @@ -102,10 +102,14 @@ public class GetResolvedJavaMethodAtSlotTest { private static void testCorrectMethods(Class holder, int methodsNumber) { for (int i = 0; i < methodsNumber; i++) { - HotSpotResolvedJavaMethodImpl method = CompilerToVMHelper + String caseName = String.format("slot %d in %s", + i, holder.getCanonicalName()); + HotSpotResolvedJavaMethod method = CompilerToVMHelper .getResolvedJavaMethodAtSlot(holder, i); - Asserts.assertNotNull(method, "Did not got method for slot " + i - + " in class " + holder.getCanonicalName()); + Asserts.assertNotNull(method, caseName + " did not got method"); + Asserts.assertEQ(holder, + CompilerToVMHelper.getMirror(method.getDeclaringClass()), + caseName + " : unexpected declaring class"); } } } diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java index e1d22fae3ce..e5db902cecf 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java @@ -25,13 +25,15 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java + * ../common/PublicMetaspaceWrapperObject.java * @build compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest * @run main ClassFileInstaller * sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * jdk.vm.ci.hotspot.CompilerToVMHelper + * jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions * -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest @@ -40,8 +42,8 @@ package compiler.jvmci.compilerToVM; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; -import jdk.vm.ci.hotspot.MetaspaceWrapperObject; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; import sun.hotspot.WhiteBox; @@ -53,23 +55,20 @@ public class GetResolvedJavaMethodTest { private static enum TestCase { NULL_BASE { @Override - HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() { + HotSpotResolvedJavaMethod getResolvedJavaMethod() { return CompilerToVMHelper.getResolvedJavaMethod( null, getPtrToMethod()); } }, JAVA_METHOD_BASE { @Override - HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() { - HotSpotResolvedJavaMethodImpl methodInstance + HotSpotResolvedJavaMethod getResolvedJavaMethod() { + HotSpotResolvedJavaMethod methodInstance = CompilerToVMHelper.getResolvedJavaMethodAtSlot( - TEST_CLASS, 0); - Field field; + TEST_CLASS, 0); try { - field = HotSpotResolvedJavaMethodImpl - .class.getDeclaredField("metaspaceMethod"); - field.setAccessible(true); - field.set(methodInstance, getPtrToMethod()); + METASPACE_METHOD_FIELD.set(methodInstance, + getPtrToMethod()); } catch (ReflectiveOperationException e) { throw new Error("TEST BUG : " + e, e); } @@ -79,19 +78,15 @@ public class GetResolvedJavaMethodTest { }, JAVA_METHOD_BASE_IN_TWO { @Override - HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() { + HotSpotResolvedJavaMethod getResolvedJavaMethod() { long ptr = getPtrToMethod(); - HotSpotResolvedJavaMethodImpl methodInstance + HotSpotResolvedJavaMethod methodInstance = CompilerToVMHelper.getResolvedJavaMethodAtSlot( TEST_CLASS, 0); - Field field; try { - field = HotSpotResolvedJavaMethodImpl - .class.getDeclaredField("metaspaceMethod"); - field.setAccessible(true); - field.set(methodInstance, ptr / 2L); + METASPACE_METHOD_FIELD.set(methodInstance, ptr / 2L); } catch (ReflectiveOperationException e) { - throw new Error("TESTBUG : " + e.getMessage(), e); + throw new Error("TESTBUG : " + e, e); } return CompilerToVMHelper.getResolvedJavaMethod(methodInstance, ptr - ptr / 2L); @@ -99,36 +94,42 @@ public class GetResolvedJavaMethodTest { }, JAVA_METHOD_BASE_ZERO { @Override - HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() { + HotSpotResolvedJavaMethod getResolvedJavaMethod() { long ptr = getPtrToMethod(); - HotSpotResolvedJavaMethodImpl methodInstance + HotSpotResolvedJavaMethod methodInstance = CompilerToVMHelper.getResolvedJavaMethodAtSlot( TEST_CLASS, 0); - Field field; try { - field = HotSpotResolvedJavaMethodImpl - .class.getDeclaredField("metaspaceMethod"); - field.setAccessible(true); - field.set(methodInstance, 0L); + METASPACE_METHOD_FIELD.set(methodInstance, 0L); } catch (ReflectiveOperationException e) { - throw new Error("TESTBUG : " + e.getMessage(), e); + throw new Error("TESTBUG : " + e, e); } return CompilerToVMHelper.getResolvedJavaMethod(methodInstance, ptr); } } ; - abstract HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(); + abstract HotSpotResolvedJavaMethod getResolvedJavaMethod(); } private static final Unsafe UNSAFE = Utils.getUnsafe(); private static final WhiteBox WB = WhiteBox.getWhiteBox(); + private static final Field METASPACE_METHOD_FIELD; private static final Class TEST_CLASS = GetResolvedJavaMethodTest.class; private static final long PTR; static { - HotSpotResolvedJavaMethodImpl method + HotSpotResolvedJavaMethod method = CompilerToVMHelper.getResolvedJavaMethodAtSlot(TEST_CLASS, 0); - PTR = method.getMetaspacePointer(); + try { + // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod + METASPACE_METHOD_FIELD = method.getClass() + .getDeclaredField("metaspaceMethod"); + METASPACE_METHOD_FIELD.setAccessible(true); + PTR = (long) METASPACE_METHOD_FIELD.get(method); + } catch (ReflectiveOperationException e) { + throw new Error("TESTBUG : " + e, e); + } + } private static long getPtrToMethod() { @@ -144,10 +145,11 @@ public class GetResolvedJavaMethodTest { public void test(TestCase testCase) { System.out.println(testCase.name()); - HotSpotResolvedJavaMethodImpl result = testCase.getResolvedJavaMethod(); + HotSpotResolvedJavaMethod result = testCase.getResolvedJavaMethod(); Asserts.assertNotNull(result, testCase + " : got null"); - Asserts.assertEQ(result.getDeclaringClass().mirror(), TEST_CLASS, - testCase + " : returned method has unexpected declaring class"); + Asserts.assertEQ(TEST_CLASS, + CompilerToVMHelper.getMirror(result.getDeclaringClass()), + testCase + " : unexpected declaring class"); } public static void main(String[] args) { @@ -161,9 +163,9 @@ public class GetResolvedJavaMethodTest { private static void testMetaspaceWrapperBase() { try { - HotSpotResolvedJavaMethodImpl method + HotSpotResolvedJavaMethod method = CompilerToVMHelper.getResolvedJavaMethod( - new MetaspaceWrapperObject() { + new PublicMetaspaceWrapperObject() { @Override public long getMetaspacePointer() { return getPtrToMethod(); @@ -171,18 +173,18 @@ public class GetResolvedJavaMethodTest { }, 0L); throw new AssertionError("Test METASPACE_WRAPPER_BASE." + " Expected IllegalArgumentException has not been caught"); - } catch (IllegalArgumentException iae) { + } catch (IllegalArgumentException e) { // expected } } private static void testObjectBase() { try { - HotSpotResolvedJavaMethodImpl method + HotSpotResolvedJavaMethod method = CompilerToVMHelper.getResolvedJavaMethod(new Object(), 0L); throw new AssertionError("Test OBJECT_BASE." + " Expected IllegalArgumentException has not been caught"); - } catch (IllegalArgumentException iae) { + } catch (IllegalArgumentException e) { // expected } } diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java index cc5f6bfff25..82561463eb4 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java @@ -25,13 +25,15 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java + * ../common/PublicMetaspaceWrapperObject.java * @build compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest * @run main ClassFileInstaller * sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * jdk.vm.ci.hotspot.CompilerToVMHelper + * jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions * -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+UseCompressedOops @@ -45,11 +47,11 @@ package compiler.jvmci.compilerToVM; import java.lang.reflect.Field; +import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotConstantPool; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; -import jdk.vm.ci.hotspot.MetaspaceWrapperObject; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; import sun.hotspot.WhiteBox; @@ -59,21 +61,22 @@ public class GetResolvedJavaTypeTest { private static enum TestCase { NULL_BASE { @Override - HotSpotResolvedObjectTypeImpl getResolvedJavaType() { + HotSpotResolvedObjectType getResolvedJavaType() { return CompilerToVMHelper.getResolvedJavaType( null, getPtrToKlass(), COMPRESSED); } }, JAVA_METHOD_BASE { @Override - HotSpotResolvedObjectTypeImpl getResolvedJavaType() { - HotSpotResolvedJavaMethodImpl methodInstance + HotSpotResolvedObjectType getResolvedJavaType() { + HotSpotResolvedJavaMethod methodInstance = CompilerToVMHelper.getResolvedJavaMethodAtSlot( TEST_CLASS, 0); Field field; try { - field = HotSpotResolvedJavaMethodImpl - .class.getDeclaredField("metaspaceMethod"); + // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod + field = methodInstance.getClass() + .getDeclaredField("metaspaceMethod"); field.setAccessible(true); field.set(methodInstance, getPtrToKlass()); } catch (ReflectiveOperationException e) { @@ -86,17 +89,18 @@ public class GetResolvedJavaTypeTest { }, CONSTANT_POOL_BASE { @Override - HotSpotResolvedObjectTypeImpl getResolvedJavaType() { - HotSpotConstantPool cpInst; + HotSpotResolvedObjectType getResolvedJavaType() { + ConstantPool cpInst; try { cpInst = CompilerToVMHelper.getConstantPool(null, getPtrToKlass()); - Field field = HotSpotConstantPool.class + // jdk.vm.ci.hotspot.HotSpotConstantPool.metaspaceConstantPool + Field field = cpInst.getClass() .getDeclaredField("metaspaceConstantPool"); field.setAccessible(true); field.set(cpInst, getPtrToKlass()); } catch (ReflectiveOperationException e) { - throw new Error("TESTBUG : " + e.getMessage(), e); + throw new Error("TESTBUG : " + e, e); } return CompilerToVMHelper.getResolvedJavaType(cpInst, 0L, COMPRESSED); @@ -104,17 +108,18 @@ public class GetResolvedJavaTypeTest { }, CONSTANT_POOL_BASE_IN_TWO { @Override - HotSpotResolvedObjectTypeImpl getResolvedJavaType() { + HotSpotResolvedObjectType getResolvedJavaType() { long ptr = getPtrToKlass(); - HotSpotConstantPool cpInst = HotSpotResolvedObjectTypeImpl - .fromObjectClass(TEST_CLASS).getConstantPool(); + ConstantPool cpInst = HotSpotResolvedObjectType + .fromObjectClass(TEST_CLASS) + .getConstantPool(); try { - Field field = HotSpotConstantPool.class + Field field = cpInst.getClass() .getDeclaredField("metaspaceConstantPool"); field.setAccessible(true); field.set(cpInst, ptr / 2L); } catch (ReflectiveOperationException e) { - throw new Error("TESTBUG : " + e.getMessage(), e); + throw new Error("TESTBUG : " + e, e); } return CompilerToVMHelper.getResolvedJavaType(cpInst, ptr - ptr / 2L, COMPRESSED); @@ -122,17 +127,18 @@ public class GetResolvedJavaTypeTest { }, CONSTANT_POOL_BASE_ZERO { @Override - HotSpotResolvedObjectTypeImpl getResolvedJavaType() { + HotSpotResolvedObjectType getResolvedJavaType() { long ptr = getPtrToKlass(); - HotSpotConstantPool cpInst = HotSpotResolvedObjectTypeImpl - .fromObjectClass(TEST_CLASS).getConstantPool(); + ConstantPool cpInst = HotSpotResolvedObjectType + .fromObjectClass(TEST_CLASS) + .getConstantPool(); try { - Field field = HotSpotConstantPool.class + Field field = cpInst.getClass() .getDeclaredField("metaspaceConstantPool"); field.setAccessible(true); field.set(cpInst, 0L); } catch (ReflectiveOperationException e) { - throw new Error("TESTBUG : " + e.getMessage(), e); + throw new Error("TESTBUG : " + e, e); } return CompilerToVMHelper.getResolvedJavaType(cpInst, ptr, COMPRESSED); @@ -140,9 +146,9 @@ public class GetResolvedJavaTypeTest { }, OBJECT_TYPE_BASE { @Override - HotSpotResolvedObjectTypeImpl getResolvedJavaType() { - HotSpotResolvedObjectTypeImpl type - = HotSpotResolvedObjectTypeImpl.fromObjectClass( + HotSpotResolvedObjectType getResolvedJavaType() { + HotSpotResolvedObjectType type + = HotSpotResolvedObjectType.fromObjectClass( OBJECT_TYPE_BASE.getClass()); long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE); return CompilerToVMHelper.getResolvedJavaType(type, @@ -150,7 +156,7 @@ public class GetResolvedJavaTypeTest { } }, ; - abstract HotSpotResolvedObjectTypeImpl getResolvedJavaType(); + abstract HotSpotResolvedObjectType getResolvedJavaType(); } private static final Unsafe UNSAFE = Utils.getUnsafe(); @@ -176,9 +182,10 @@ public class GetResolvedJavaTypeTest { public void test(TestCase testCase) { System.out.println(testCase.name()); - HotSpotResolvedObjectTypeImpl type = testCase.getResolvedJavaType(); - Asserts.assertEQ(type.mirror(), TEST_CLASS, testCase + - " Unexpected Class returned by getResolvedJavaType"); + HotSpotResolvedObjectType type = testCase.getResolvedJavaType(); + Asserts.assertEQ(TEST_CLASS, + CompilerToVMHelper.getMirror(type), + testCase + " : unexpected class returned"); } public static void main(String[] args) { @@ -192,9 +199,9 @@ public class GetResolvedJavaTypeTest { private static void testMetaspaceWrapperBase() { try { - HotSpotResolvedObjectTypeImpl type + HotSpotResolvedObjectType type = CompilerToVMHelper.getResolvedJavaType( - new MetaspaceWrapperObject() { + new PublicMetaspaceWrapperObject() { @Override public long getMetaspacePointer() { return getPtrToKlass(); @@ -209,7 +216,7 @@ public class GetResolvedJavaTypeTest { private static void testObjectBase() { try { - HotSpotResolvedObjectTypeImpl type + HotSpotResolvedObjectType type = CompilerToVMHelper.getResolvedJavaType(new Object(), 0L, COMPRESSED); throw new AssertionError("Test OBJECT_BASE." diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java index 389fb66a6a2..3bbb5b29a72 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI @@ -41,7 +41,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; @@ -53,7 +53,7 @@ public class GetStackTraceElementTest { } private static void runSanityTest(Executable aMethod, int[] bcis) { - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); String className = aMethod.getDeclaringClass().getName(); int lastDot = className.lastIndexOf('.'); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java index 2a2d2664350..201faa364c7 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.GetSymbolTest * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper @@ -52,7 +52,7 @@ import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.ConstantPool; import jdk.test.lib.Utils; @@ -76,7 +76,7 @@ public class GetSymbolTest { } catch (NoSuchMethodException e) { throw new Error("TEST BUG: can't find test method", e); } - HotSpotResolvedJavaMethodImpl resolvedMethod + HotSpotResolvedJavaMethod resolvedMethod = CTVMUtilities.getResolvedMethod(aClass, method); List symbols; try { @@ -101,7 +101,7 @@ public class GetSymbolTest { } } - private List getSymbols(HotSpotResolvedJavaMethodImpl + private List getSymbols(HotSpotResolvedJavaMethod metaspaceMethod) throws ReflectiveOperationException { List symbols = new ArrayList<>(); ConstantPool pool = metaspaceMethod.getConstantPool(); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java index 682b9a0fa86..ae68ebe2286 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.GetVtableIndexForInterfaceTest * @run main ClassFileInstaller @@ -53,8 +53,8 @@ import java.util.HashSet; import java.util.Set; import java.util.stream.Stream; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; @@ -125,10 +125,10 @@ public class GetVtableIndexForInterfaceTest { private void runTest(TestCase tcase) throws NoSuchMethodException { System.out.println(tcase); Method method = tcase.holder.getDeclaredMethod(tcase.methodName); - HotSpotResolvedObjectTypeImpl metaspaceKlass = CompilerToVMHelper + HotSpotResolvedObjectType metaspaceKlass = CompilerToVMHelper .lookupType(Utils.toJVMTypeSignature(tcase.receiver), getClass(), /* resolve = */ true); - HotSpotResolvedJavaMethodImpl metaspaceMethod = CTVMUtilities + HotSpotResolvedJavaMethod metaspaceMethod = CTVMUtilities .getResolvedMethod(tcase.holder, method); int index = 0; try { diff --git a/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java b/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java index 7db6ef08141..e772a912406 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -43,22 +43,19 @@ package compiler.jvmci.compilerToVM; import compiler.jvmci.common.CTVMUtilities; import java.lang.reflect.Executable; -import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import compiler.testlibrary.CompilerUtils; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; -import sun.hotspot.WhiteBox; +import jdk.test.lib.Utils; import sun.hotspot.code.NMethod; public class HasCompiledCodeForOSRTest { public static void main(String[] args) { - ListtestCases = createTestCases(); + List testCases = createTestCases(); testCases.forEach(HasCompiledCodeForOSRTest::runSanityTest); } @@ -67,7 +64,8 @@ public class HasCompiledCodeForOSRTest { try { Class aClass = DummyClass.class; - testCases.add(new CompileCodeTestCase( + Object receiver = new DummyClass(); + testCases.add(new CompileCodeTestCase(receiver, aClass.getMethod("withLoop"), 17)); } catch (NoSuchMethodException e) { throw new Error("TEST BUG : " + e.getMessage(), e); @@ -78,8 +76,9 @@ public class HasCompiledCodeForOSRTest { private static void runSanityTest(CompileCodeTestCase testCase) { System.out.println(testCase); Executable aMethod = testCase.executable; - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); + testCase.invoke(Utils.getNullValues(aMethod.getParameterTypes())); testCase.deoptimize(); int[] levels = CompilerUtils.getAvailableCompilationLevels(); // not compiled @@ -98,7 +97,9 @@ public class HasCompiledCodeForOSRTest { boolean isCompiled; int level = nm.comp_level; - for (int i : levels) { + int[] someLevels = new int[] {-4, 0, 1, 2, 3, 4, 5, 45}; + // check levels + for (int i : someLevels) { isCompiled = CompilerToVMHelper.hasCompiledCodeForOSR( method, testCase.bci, i); Asserts.assertEQ(isCompiled, level == i, String.format( @@ -106,8 +107,20 @@ public class HasCompiledCodeForOSRTest { + "level %d", testCase, i)); } - for (int i : new int[] {-1, +1}) { - int bci = testCase.bci + i; + // check bci + byte[] bytecode = CompilerToVMHelper.getBytecode(CTVMUtilities + .getResolvedMethod(testCase.executable)); + int[] incorrectBci = new int[] { + testCase.bci + 1, + testCase.bci - 1, + -200, + -10, + bytecode.length, + bytecode.length + 1, + bytecode.length + 4, + bytecode.length + 200 + }; + for (int bci : incorrectBci) { isCompiled = CompilerToVMHelper.hasCompiledCodeForOSR( method, bci, level); Asserts.assertFalse(isCompiled, String.format( diff --git a/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java b/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java index 4a52691a9be..806a19e5c9c 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.HasFinalizableSubclassTest * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper @@ -45,7 +45,7 @@ import java.util.HashSet; import java.util.Set; import java.util.stream.Stream; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; @@ -81,7 +81,7 @@ public class HasFinalizableSubclassTest { private void runTest(TestCase tcase) { System.out.println(tcase); - HotSpotResolvedObjectTypeImpl metaspaceKlass = CompilerToVMHelper + HotSpotResolvedObjectType metaspaceKlass = CompilerToVMHelper .lookupType(Utils.toJVMTypeSignature(tcase.aClass), getClass(), /* resolve = */ true); Asserts.assertEQ(tcase.expected, diff --git a/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java b/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java index 0655d4c1d43..35fe8d18980 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java @@ -44,6 +44,7 @@ import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Consumer; import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; import sun.misc.Unsafe; @@ -72,7 +73,7 @@ public class InitializeConfigurationTest { private void runTest(List tcases) { VMStructDataReader reader = new VMStructDataReader( - CompilerToVMHelper.initializeConfiguration()); + CompilerToVMHelper.initializeConfiguration(HotSpotJVMCIRuntime.runtime().getConfig())); while (reader.hasNext()) { VMFieldData data = reader.next(); for (TestCase tcase : tcases) { diff --git a/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java index 1db21f10718..c76f62f28c1 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @ignore 8139700 * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox @@ -41,14 +41,25 @@ package compiler.jvmci.compilerToVM; +import compiler.jvmci.common.CTVMUtilities; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; import sun.hotspot.code.NMethod; import java.util.List; +import jdk.vm.ci.code.CodeCacheProvider; +import jdk.vm.ci.code.CompilationResult; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; public class InvalidateInstalledCodeTest { + private static final CodeCacheProvider CACHE_PROVIDER + = HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend() + .getCodeCache(); + public static void main(String[] args) { InvalidateInstalledCodeTest test = new InvalidateInstalledCodeTest(); @@ -60,26 +71,37 @@ public class InvalidateInstalledCodeTest { } private void checkNull() { - InstalledCode installedCode = new InstalledCode(""); - installedCode.setAddress(0); - CompilerToVMHelper.invalidateInstalledCode(installedCode); + Utils.runAndCheckException( + () -> CompilerToVMHelper.invalidateInstalledCode(null), + NullPointerException.class); } private void check(CompileCodeTestCase testCase) { System.out.println(testCase); - // to have a clean state - NMethod beforeInvalidation = testCase.deoptimizeAndCompile(); - if (beforeInvalidation == null) { - throw new Error("method is not compiled, testCase " + testCase); - } + HotSpotResolvedJavaMethod javaMethod + = CTVMUtilities.getResolvedMethod(testCase.executable); + HotSpotCompilationRequest compRequest = new HotSpotCompilationRequest( + javaMethod, testCase.bci, /* jvmciEnv = */ 0L); + String name = testCase.executable.getName(); + CompilationResult compResult = new CompilationResult(name); + // to pass sanity check of default -1 + compResult.setTotalFrameSize(0); + InstalledCode installedCode = CACHE_PROVIDER.installCode( + compRequest, compResult, + new InstalledCode(name), /* speculationLog = */ null, + /* isDefault = */ false); + Asserts.assertTrue(installedCode.isValid(), testCase + + " : code is invalid even before invalidation"); + NMethod beforeInvalidation = testCase.toNMethod(); + if (beforeInvalidation != null) { + throw new Error("TESTBUG : " + testCase + " : nmethod isn't found"); + } // run twice to verify how it works if method is already invalidated for (int i = 0; i < 2; ++i) { - InstalledCode installedCode = new InstalledCode( - testCase.executable.getName()); - installedCode.setAddress(beforeInvalidation.address); - CompilerToVMHelper.invalidateInstalledCode(installedCode); + Asserts.assertFalse(installedCode.isValid(), testCase + + " : code is valid after invalidation, i = " + i); NMethod afterInvalidation = testCase.toNMethod(); if (afterInvalidation != null) { System.err.println("before: " + beforeInvalidation); @@ -87,8 +109,6 @@ public class InvalidateInstalledCodeTest { throw new AssertionError(testCase + " : method hasn't been invalidated, i = " + i); } - Asserts.assertFalse(installedCode.isValid(), testCase - + " : code is valid after invalidation, i = " + i); } } } diff --git a/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java b/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java index 214b9153e7d..b4f89d67877 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox IsMatureTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java index ddbc028be0a..00378a00ed7 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java @@ -22,7 +22,7 @@ * */ -/** +/* * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" @@ -40,7 +40,6 @@ package compiler.jvmci.compilerToVM; -import jdk.vm.ci.hotspot.CompilerToVM; import jdk.vm.ci.runtime.JVMCI; import jdk.test.lib.Asserts; @@ -88,9 +87,12 @@ public class JVM_RegisterJVMCINatives { private JVM_RegisterJVMCINatives() { Method method; try { - method = CompilerToVM.class.getDeclaredMethod("registerNatives"); + method = Class.forName("jdk.vm.ci.hotspot.CompilerToVM", + /* initialize = */ false, + this.getClass().getClassLoader()) + .getDeclaredMethod("registerNatives"); method.setAccessible(true); - } catch (NoSuchMethodException e) { + } catch (ReflectiveOperationException e) { throw new Error("can't find CompilerToVM::registerNatives", e); } registerNatives = method; diff --git a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java index 1db92682d43..0451c71baa4 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java @@ -27,7 +27,7 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" * @summary Testing compiler.jvmci.CompilerToVM.lookupKlassInPool method - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.common.testcases.MultipleImplementersInterface * compiler.jvmci.common.testcases.MultipleImplementer2 @@ -44,8 +44,7 @@ package compiler.jvmci.compilerToVM; import java.util.HashMap; import java.util.Map; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotConstantPool; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import sun.reflect.ConstantPool; /** @@ -62,16 +61,16 @@ public class LookupKlassInPoolTest { testCase.test(); } - public static void validate(HotSpotConstantPool constantPoolCTVM, + public static void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM, ConstantPool constantPoolSS, ConstantPoolTestsHelper.DummyClasses dummyClass, int i) { Object classToVerify = CompilerToVMHelper .lookupKlassInPool(constantPoolCTVM, i); - if (!(classToVerify instanceof HotSpotResolvedObjectTypeImpl) + if (!(classToVerify instanceof HotSpotResolvedObjectType) && !(classToVerify instanceof String)) { String msg = String.format("Output of method" + " CTVM.lookupKlassInPool is neither" - + " a HotSpotResolvedObjectTypeImpl, nor a String"); + + " a HotSpotResolvedObjectType, nor a String"); throw new AssertionError(msg); } int classNameIndex = (int) dummyClass.cp.get(i).value; diff --git a/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java index 50142e50e69..571bf159660 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java @@ -42,7 +42,7 @@ import compiler.jvmci.common.testcases.SingleSubclass; import java.util.HashSet; import java.util.Set; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; @@ -86,7 +86,7 @@ public class LookupTypeTest { private void runTest(TestCase tcase) { System.out.println(tcase); - HotSpotResolvedObjectTypeImpl metaspaceKlass; + HotSpotResolvedObjectType metaspaceKlass; try { metaspaceKlass = CompilerToVMHelper.lookupType(tcase.className, tcase.accessing, tcase.resolve); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java b/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java index 2f63fcdc0ba..fce33de6d6b 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @ignore 8139703 * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox MaterializeVirtualObjectTest @@ -46,19 +46,21 @@ package compiler.jvmci.compilerToVM; -import compiler.jvmci.common.CTVMUtilities; -import compiler.testlibrary.CompilerUtils; +import java.lang.reflect.Method; +import jdk.vm.ci.hotspot.HotSpotStackFrameReference; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; + +import compiler.jvmci.common.CTVMUtilities; +import compiler.testlibrary.CompilerUtils; + import sun.hotspot.WhiteBox; -import java.lang.reflect.Method; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; -import jdk.vm.ci.hotspot.HotSpotStackFrameReference; public class MaterializeVirtualObjectTest { private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final Method METHOD; - private static final HotSpotResolvedJavaMethodImpl RESOLVED_METHOD; + private static final ResolvedJavaMethod RESOLVED_METHOD; private static final boolean INVALIDATE = Boolean.getBoolean( "compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate"); @@ -113,7 +115,7 @@ public class MaterializeVirtualObjectTest { if (materialize) { HotSpotStackFrameReference hsFrame = CompilerToVMHelper .getNextStackFrame(/* topmost frame */ null, - new HotSpotResolvedJavaMethodImpl[]{ + new ResolvedJavaMethod[]{ RESOLVED_METHOD}, /* don't skip any */ 0); Asserts.assertNotNull(hsFrame, getName() + " : got null frame"); Asserts.assertTrue(WB.isMethodCompiled(METHOD), getName() diff --git a/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java b/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java index 746d5ee9100..4d228cd967f 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI @@ -41,7 +41,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Executable; import java.util.HashMap; import java.util.Map; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; @@ -54,7 +54,7 @@ public class MethodIsIgnoredBySecurityStackWalkTest { } private static void runSanityTest(Executable aMethod, Boolean expected) { - HotSpotResolvedJavaMethodImpl method + HotSpotResolvedJavaMethod method = CTVMUtilities.getResolvedMethod(aMethod); boolean isIgnored = CompilerToVMHelper .methodIsIgnoredBySecurityStackWalk(method); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java index db8ab1c3672..7b752228962 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib/ + * @library / /testlibrary /test/lib/ * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.ReadUncompressedOopTest * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java index 24fa5b589b9..d010e67e21f 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller @@ -46,7 +46,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Random; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.meta.ProfilingInfo; import jdk.test.lib.Asserts; @@ -78,7 +78,7 @@ public class ReprofileTest { } private static void runSanityTest(Method aMethod) { - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); ProfilingInfo startProfile = method.getProfilingInfo(); Asserts.assertFalse(startProfile.isMature(), aMethod diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java index ffbecca7dbf..0735ccb154d 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.ResolveConstantInPoolTest * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper @@ -42,7 +42,6 @@ import java.lang.invoke.MethodType; import java.util.HashMap; import java.util.Map; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotConstantPool; import jdk.test.lib.Asserts; import sun.reflect.ConstantPool; @@ -62,7 +61,8 @@ public class ResolveConstantInPoolTest { testCase.test(); } - private static void validateMethodHandle(HotSpotConstantPool constantPoolCTVM, + private static void validateMethodHandle( + jdk.vm.ci.meta.ConstantPool constantPoolCTVM, ConstantPool constantPoolSS, ConstantPoolTestsHelper.DummyClasses dummyClass, int index) { Object constantInPool = CompilerToVMHelper @@ -77,7 +77,8 @@ public class ResolveConstantInPoolTest { } } - private static void validateMethodType(HotSpotConstantPool constantPoolCTVM, + private static void validateMethodType( + jdk.vm.ci.meta.ConstantPool constantPoolCTVM, ConstantPool constantPoolSS, ConstantPoolTestsHelper.DummyClasses dummyClass, int index) { Object constantInPool = CompilerToVMHelper diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java index 8881d7a9f9f..e9e69f470f5 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib + * @library / /testlibrary /test/lib * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.ResolveMethodTest * @run main ClassFileInstaller @@ -49,8 +49,8 @@ import compiler.jvmci.common.CTVMUtilities; import java.util.HashSet; import java.util.Set; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; import sun.misc.Unsafe; @@ -125,16 +125,16 @@ public class ResolveMethodTest { private void runTest(TestCase tcase) throws NoSuchMethodException { System.out.println(tcase); - HotSpotResolvedJavaMethodImpl metaspaceMethod = CTVMUtilities + HotSpotResolvedJavaMethod metaspaceMethod = CTVMUtilities .getResolvedMethod(tcase.holder, tcase.holder.getDeclaredMethod(tcase.methodName)); - HotSpotResolvedObjectTypeImpl holderMetaspace = CompilerToVMHelper + HotSpotResolvedObjectType holderMetaspace = CompilerToVMHelper .lookupType(Utils.toJVMTypeSignature(tcase.holder), getClass(), /* resolve = */ true); - HotSpotResolvedObjectTypeImpl callerMetaspace = CompilerToVMHelper + HotSpotResolvedObjectType callerMetaspace = CompilerToVMHelper .lookupType(Utils.toJVMTypeSignature(tcase.caller), getClass(), /* resolve = */ true); - HotSpotResolvedJavaMethodImpl resolvedMetaspaceMethod + HotSpotResolvedJavaMethod resolvedMetaspaceMethod = CompilerToVMHelper.resolveMethod(holderMetaspace, metaspaceMethod, callerMetaspace); if (tcase.isPositive) { diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java index 3a98e76282c..a92800bb8dd 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java @@ -27,7 +27,7 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" * @summary Testing compiler.jvmci.CompilerToVM.resolveTypeInPool method - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.common.testcases.MultipleImplementersInterface * compiler.jvmci.common.testcases.MultipleImplementer2 @@ -44,8 +44,7 @@ package compiler.jvmci.compilerToVM; import java.util.HashMap; import java.util.Map; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotConstantPool; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import sun.reflect.ConstantPool; /** @@ -62,10 +61,11 @@ public class ResolveTypeInPoolTest { testCase.test(); } - public static void validate(HotSpotConstantPool constantPoolCTVM, + public static void validate( + jdk.vm.ci.meta.ConstantPool constantPoolCTVM, ConstantPool constantPoolSS, ConstantPoolTestsHelper.DummyClasses dummyClass, int i) { - HotSpotResolvedObjectTypeImpl typeToVerify = CompilerToVMHelper + HotSpotResolvedObjectType typeToVerify = CompilerToVMHelper .resolveTypeInPool(constantPoolCTVM, i); int classNameIndex = (int) dummyClass.cp.get(i).value; String classNameToRefer = constantPoolSS.getUTF8At(classNameIndex); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java index 820ef850171..d7a4c84caad 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java @@ -25,7 +25,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary /../../test/lib/ + * @library / /testlibrary /test/lib/ * @compile ../common/CompilerToVMHelper.java * @build compiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java index e709449a8be..e2e35719ba9 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java @@ -26,7 +26,7 @@ * @test * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library /testlibrary /../../test/lib / + * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -45,7 +45,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.test.lib.Asserts; import sun.hotspot.WhiteBox; @@ -59,7 +59,7 @@ public class ShouldInlineMethodTest { } private static void runSanityTest(Executable aMethod) { - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); boolean shouldInline = CompilerToVMHelper.shouldInlineMethod(method); boolean expectedShouldInline = WB.testSetForceInlineMethod(aMethod, diff --git a/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.config b/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.config deleted file mode 100644 index f9f1333a238..00000000000 --- a/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.config +++ /dev/null @@ -1 +0,0 @@ -compiler.jvmci.events.JvmciCompleteInitializationTest diff --git a/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.java b/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.java deleted file mode 100644 index 742878c0dfa..00000000000 --- a/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2015, 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 8136421 - * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" - * @library / /testlibrary - * @build compiler.jvmci.common.JVMCIHelpers - * compiler.jvmci.events.JvmciCompleteInitializationTest - * @run main jdk.test.lib.FileInstaller ../common/services/ ./META-INF/services/ - * @run main jdk.test.lib.FileInstaller ./JvmciCompleteInitializationTest.config - * ./META-INF/services/jdk.vm.ci.hotspot.HotSpotVMEventListener - * @run main ClassFileInstaller - * compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler - * compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory - * compiler.jvmci.events.JvmciCompleteInitializationTest - * jdk.test.lib.Asserts - * @run main/othervm -XX:+UnlockExperimentalVMOptions - * -Xbootclasspath/a:. - * -XX:+EnableJVMCI - * -Dcompiler.jvmci.events.JvmciCompleteInitializationTest.positive=true - * compiler.jvmci.events.JvmciCompleteInitializationTest - * @run main/othervm -XX:+UnlockExperimentalVMOptions - * -Xbootclasspath/a:. - * -XX:-EnableJVMCI - * -Dcompiler.jvmci.events.JvmciCompleteInitializationTest.positive=false - * compiler.jvmci.events.JvmciCompleteInitializationTest - */ - -package compiler.jvmci.events; - -import jdk.test.lib.Asserts; -import jdk.vm.ci.hotspot.HotSpotVMEventListener; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; - -public class JvmciCompleteInitializationTest implements HotSpotVMEventListener { - private static final boolean IS_POSITIVE = Boolean.getBoolean( - "compiler.jvmci.events.JvmciCompleteInitializationTest.positive"); - private static volatile int completeInitializationCount = 0; - private static volatile String errorMessage = ""; - - public static void main(String args[]) { - if (completeInitializationCount != 0) { - throw new Error("Unexpected completeInitialization events" - + " count at start"); - } - initializeRuntime(); - int expectedEventCount = IS_POSITIVE ? 1 : 0; - Asserts.assertEQ(completeInitializationCount, expectedEventCount, - "Unexpected completeInitialization events count" - + " after JVMCI init"); - initializeRuntime(); - Asserts.assertEQ(completeInitializationCount, expectedEventCount, - "Unexpected completeInitialization events count" - + " after 2nd JVMCI init"); - Asserts.assertTrue(errorMessage.isEmpty(), errorMessage); - } - - private static void initializeRuntime() { - Error t = null; - try { - /* in case JVMCI disabled, an InternalError on initialization - and NoClassDefFound on 2nd try */ - HotSpotJVMCIRuntime.runtime(); - } catch (Error e) { - t = e; - } - if (IS_POSITIVE) { - Asserts.assertNull(t, "Caught unexpected exception"); - } else { - Asserts.assertNotNull(t, "Got no expected error"); - } - } - - @Override - public void completeInitialization(HotSpotJVMCIRuntime - hotSpotJVMCIRuntime) { - completeInitializationCount++; - if (hotSpotJVMCIRuntime == null) { - errorMessage += " HotSpotJVMCIRuntime is null."; - } - } -} diff --git a/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java index 82591452d8c..7ad73d87912 100644 --- a/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java +++ b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java @@ -61,8 +61,9 @@ import jdk.vm.ci.hotspot.HotSpotVMEventListener; import jdk.vm.ci.code.CompilationResult; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; public class JvmciNotifyInstallEventTest implements HotSpotVMEventListener { private static final String METHOD_NAME = "testMethod"; @@ -99,17 +100,18 @@ public class JvmciNotifyInstallEventTest implements HotSpotVMEventListener { } catch (NoSuchMethodException e) { throw new Error("TEST BUG: Can't find " + METHOD_NAME, e); } - HotSpotResolvedJavaMethodImpl method = CTVMUtilities + HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(SimpleClass.class, testMethod); CompilationResult compResult = new CompilationResult(METHOD_NAME); + HotSpotCompilationRequest compRequest = new HotSpotCompilationRequest(method, -1, 0L); // to pass sanity check of default -1 compResult.setTotalFrameSize(0); - codeCache.installMethod(method, compResult, /* jvmciEnv = */ 0L, + codeCache.installCode(compRequest, compResult, /* installedCode = */ null, /* speculationLog = */ null, /* isDefault = */ false); Asserts.assertEQ(gotInstallNotification, 1, "Got unexpected event count after 1st install attempt"); // since "empty" compilation result is ok, a second attempt should be ok - codeCache.installMethod(method, compResult, /* jvmciEnv = */ 0L, + codeCache.installCode(compRequest, compResult, /* installedCode = */ null, /* speculationLog = */ null, /* isDefault = */ false); Asserts.assertEQ(gotInstallNotification, 2, "Got unexpected event count after 2nd install attempt"); diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/NestedBooleanOptionValueTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/NestedBooleanOptionValueTest.java index a9648ea676e..552a9937574 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/NestedBooleanOptionValueTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/NestedBooleanOptionValueTest.java @@ -29,12 +29,20 @@ package jdk.vm.ci.options.test; -import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.*; -import static org.junit.Assert.*; -import jdk.vm.ci.options.*; -import jdk.vm.ci.options.OptionValue.*; +import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.Master0; +import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.Master1; +import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.Master2; +import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.NestedOption0; +import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.NestedOption1; +import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.NestedOption2; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import jdk.vm.ci.options.NestedBooleanOptionValue; +import jdk.vm.ci.options.OptionDescriptor; +import jdk.vm.ci.options.OptionValue; +import jdk.vm.ci.options.OptionValue.OverrideScope; -import org.junit.*; +import org.junit.Test; public class NestedBooleanOptionValueTest { diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/TestOptionValue.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/TestOptionValue.java index 17135e43e94..b9872d76fdd 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/TestOptionValue.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/TestOptionValue.java @@ -29,15 +29,21 @@ package jdk.vm.ci.options.test; -import static jdk.vm.ci.options.test.TestOptionValue.Options.*; -import static org.junit.Assert.*; +import static jdk.vm.ci.options.test.TestOptionValue.Options.Mutable; +import static jdk.vm.ci.options.test.TestOptionValue.Options.SecondMutable; +import static jdk.vm.ci.options.test.TestOptionValue.Options.Stable; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; -import java.util.*; +import java.util.Arrays; -import jdk.vm.ci.options.*; -import jdk.vm.ci.options.OptionValue.*; +import jdk.vm.ci.options.OptionDescriptor; +import jdk.vm.ci.options.OptionValue; +import jdk.vm.ci.options.OptionValue.OverrideScope; +import jdk.vm.ci.options.StableOptionValue; -import org.junit.*; +import org.junit.Test; @SuppressWarnings("try") public class TestOptionValue { diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java index 3aebfec6189..ab214fd66ad 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java @@ -30,9 +30,11 @@ package jdk.vm.ci.runtime.test; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; -import org.junit.*; +import org.junit.Assert; +import org.junit.Test; public class ConstantTest extends FieldUniverse { diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/FieldUniverse.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/FieldUniverse.java index 72f64ade918..e8d325024a0 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/FieldUniverse.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/FieldUniverse.java @@ -22,10 +22,11 @@ */ package jdk.vm.ci.runtime.test; -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ResolvedJavaField; /** * Context for field related tests. diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/MethodUniverse.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/MethodUniverse.java index f7f59e82c54..35368ebeca4 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/MethodUniverse.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/MethodUniverse.java @@ -22,10 +22,12 @@ */ package jdk.vm.ci.runtime.test; -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Context for method related tests. diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java index 95341f347f3..d7fc033158e 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java @@ -22,11 +22,14 @@ */ package jdk.vm.ci.runtime.test; -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.Method; +import java.util.Arrays; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.runtime.*; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.runtime.JVMCI; class NameAndSignature { diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java index 84def0f2c77..f7422fbce78 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java @@ -30,22 +30,31 @@ package jdk.vm.ci.runtime.test; -import static org.junit.Assume.*; +import static org.junit.Assume.assumeTrue; -import java.io.*; -import java.lang.instrument.*; -import java.lang.management.*; -import java.lang.reflect.*; -import java.nio.file.*; -import java.security.*; -import java.util.*; -import java.util.jar.*; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.ProtectionDomain; +import java.util.Arrays; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; -import javax.tools.*; +import javax.tools.ToolProvider; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ResolvedJavaMethod; -import org.junit.*; +import org.junit.Assert; +import org.junit.Test; /** * Tests that {@link ResolvedJavaMethod}s are safe in the context of class redefinition being used diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java index 6e7db7c08cc..f6d38b44bbd 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java @@ -29,11 +29,14 @@ package jdk.vm.ci.runtime.test; -import static org.junit.Assert.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.runtime.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.runtime.JVMCI; -import org.junit.*; +import org.junit.Test; public class ResolvedJavaTypeResolveConcreteMethodTest { public final MetaAccessProvider metaAccess; diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java index 580c353da90..2b5d05c60d5 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java @@ -29,11 +29,14 @@ package jdk.vm.ci.runtime.test; -import static org.junit.Assert.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.runtime.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.runtime.JVMCI; -import org.junit.*; +import org.junit.Test; public class ResolvedJavaTypeResolveMethodTest { public final MetaAccessProvider metaAccess; diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java index 7d5c265ef5e..bdb258038b8 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java @@ -30,14 +30,20 @@ package jdk.vm.ci.runtime.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.Array; +import java.util.List; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; -import org.junit.*; +import org.junit.Test; /** * Tests for {@link ConstantReflectionProvider}. It assumes an implementation of the interface that diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java index f0a6c7d3657..1dea56cc20a 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java @@ -30,14 +30,19 @@ package jdk.vm.ci.runtime.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.Field; +import java.util.Map; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaField; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; -import org.junit.*; +import org.junit.Test; /** * Tests for {@link JavaField}. diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java index 185bc29fcd1..f5e5b368e3e 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java @@ -30,14 +30,17 @@ package jdk.vm.ci.runtime.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.Method; +import java.util.Map; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; -import org.junit.*; +import org.junit.Test; /** * Tests for {@link JavaMethod}. diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java index 62a13a24292..e17427bf432 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java @@ -30,10 +30,11 @@ package jdk.vm.ci.runtime.test; -import jdk.vm.ci.meta.*; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; -import org.junit.*; +import org.junit.Test; /** * Tests for {@link JavaType}. diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java index 968066d59db..c0420f4f5e4 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java @@ -30,14 +30,22 @@ package jdk.vm.ci.runtime.test; -import static jdk.vm.ci.meta.MetaUtil.*; -import static org.junit.Assert.*; +import static jdk.vm.ci.meta.MetaUtil.toInternalName; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; -import java.lang.reflect.*; +import java.lang.reflect.Field; +import java.lang.reflect.Method; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; -import org.junit.*; +import org.junit.Test; /** * Tests for {@link MetaAccessProvider}. diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java index 88b3b5f9751..4b0c4df2c74 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java @@ -30,15 +30,27 @@ package jdk.vm.ci.runtime.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.util.*; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.LocationIdentity; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; -import org.junit.*; +import org.junit.Test; /** * Tests for {@link ResolvedJavaField}. diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java index 2b0f7b4aab4..39ef621f924 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java @@ -30,16 +30,35 @@ package jdk.vm.ci.runtime.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; -import java.lang.annotation.*; -import java.lang.invoke.*; -import java.lang.reflect.*; -import java.util.*; +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.ExceptionHandler; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; -import org.junit.*; +import org.junit.Assert; +import org.junit.Test; /** * Tests for {@link ResolvedJavaMethod}. diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 42520f7d8ea..2ddf7797fcc 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -30,19 +30,42 @@ package jdk.vm.ci.runtime.test; -import static java.lang.reflect.Modifier.*; -import static org.junit.Assert.*; +import static java.lang.reflect.Modifier.isAbstract; +import static java.lang.reflect.Modifier.isFinal; +import static java.lang.reflect.Modifier.isPrivate; +import static java.lang.reflect.Modifier.isProtected; +import static java.lang.reflect.Modifier.isPublic; +import static java.lang.reflect.Modifier.isStatic; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.net.*; -import java.util.*; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.meta.Assumptions.*; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.Assumptions.AssumptionResult; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ModifiersProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.TrustedInterface; -import org.junit.*; +import org.junit.Test; import sun.reflect.ConstantPool; diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java index 0cb74ed83f4..f2a187effa8 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java @@ -22,20 +22,42 @@ */ package jdk.vm.ci.runtime.test; -import static java.lang.reflect.Modifier.*; +import static java.lang.reflect.Modifier.isFinal; +import static java.lang.reflect.Modifier.isStatic; -import java.io.*; -import java.lang.reflect.*; -import java.util.*; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.AbstractCollection; +import java.util.AbstractList; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.Queue; -import java.util.stream.*; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Collectors; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.runtime.*; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaField; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.TrustedInterface; +import jdk.vm.ci.runtime.JVMCI; -import org.junit.*; +import org.junit.Test; -import sun.misc.*; +import sun.misc.Unsafe; //JaCoCo Exclude diff --git a/hotspot/test/compiler/membars/DekkerTest.java b/hotspot/test/compiler/membars/DekkerTest.java index f4f2826b6e4..bef045701ec 100644 --- a/hotspot/test/compiler/membars/DekkerTest.java +++ b/hotspot/test/compiler/membars/DekkerTest.java @@ -25,9 +25,9 @@ * @test * @bug 8007898 * @summary Incorrect optimization of Memory Barriers in Matcher::post_store_load_barrier(). - * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:-TieredCompilation -XX:+StressGCM -XX:+StressLCM DekkerTest - * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:-TieredCompilation -XX:+StressGCM -XX:+StressLCM DekkerTest - * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:-TieredCompilation -XX:+StressGCM -XX:+StressLCM DekkerTest + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest * @author Martin Doerr martin DOT doerr AT sap DOT com * * Run 3 times since the failure is intermittent. diff --git a/hotspot/test/compiler/oracle/GetMethodOptionTest.java b/hotspot/test/compiler/oracle/GetMethodOptionTest.java index de446548d33..a6b92b2c632 100644 --- a/hotspot/test/compiler/oracle/GetMethodOptionTest.java +++ b/hotspot/test/compiler/oracle/GetMethodOptionTest.java @@ -30,7 +30,7 @@ import sun.hotspot.WhiteBox; /* * @test * @bug 8074980 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build sun.hotspot.WhiteBox jdk.test.lib.Asserts GetMethodOptionTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/oracle/MethodMatcherTest.java b/hotspot/test/compiler/oracle/MethodMatcherTest.java index 96298d27d62..386f24406c8 100644 --- a/hotspot/test/compiler/oracle/MethodMatcherTest.java +++ b/hotspot/test/compiler/oracle/MethodMatcherTest.java @@ -23,7 +23,8 @@ /* * @test MethodMatcherTest - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib + * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI MethodMatcherTest diff --git a/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java b/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java index eadd8ee7642..bd54edef523 100644 --- a/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java +++ b/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java @@ -25,7 +25,7 @@ * @test * @bug 8073480 * @summary explicit range checks should be recognized by C2 - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * @build TestExplicitRangeChecks * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller jdk.test.lib.Platform diff --git a/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java b/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java index e1857fa12f1..c66fac104fd 100644 --- a/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java +++ b/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java @@ -25,7 +25,7 @@ * @test * @bug 8066103 * @summary C2's range check smearing allows out of bound array accesses - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * @modules java.base/sun.misc * java.management * @build TestRangeCheckSmearing diff --git a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java index fefee144a21..1ef29fa3593 100644 --- a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify PrintPreciseRTMLockingStatistics on CPUs with * rtm support and on VM with rtm locking support, - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java index c64e1e86187..389141fe016 100644 --- a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify PrintPreciseRTMLockingStatistics on CPUs without * rtm support and/or unsupported VM. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java index 37f94390a4c..7e6b3960d03 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify RTMAbortRatio option processing on CPU with rtm * support and on VM with rtm locking support. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMAbortRatioOptionOnSupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java index 0eae1c68617..17a66529deb 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify RTMAbortRatio option processing on CPU without rtm * support or on VM that does not support rtm locking. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMAbortRatioOptionOnUnsupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java index 93e0222fd34..cde17b4482c 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify RTMTotalCountIncrRate option processing on CPU with * rtm support and on VM with rtm locking support. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMTotalCountIncrRateOptionOnSupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java index eeb86d73eec..222ffa25793 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java @@ -32,7 +32,7 @@ import rtm.predicate.SupportedVM; * @bug 8031320 * @summary Verify RTMTotalCountIncrRate option processing on CPU without * rtm support and/or on VM without rtm locking support. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMTotalCountIncrRateOptionOnUnsupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java index 307d085e8e4..af702f6520a 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMDeopt option processing on CPUs with rtm support * when rtm locking is supported by VM. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMDeoptOptionOnSupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java index b367bdad9fa..ba9970d077a 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMDeopt option processing on CPUs without rtm support * or on VMs without rtm locking support. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMDeoptOptionOnUnsupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java index 04c507ccf82..128b0efc06c 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMForStackLocks option processing on CPU with * rtm support when VM supports rtm locking. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMForStackLocksOptionOnSupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java index 28d2d8b06b7..3e22b07a744 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMForStackLocks option processing on CPUs without * rtm support and/or on VMs without rtm locking support. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMForStackLocksOptionOnUnsupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java index 821687695a8..6939d13f8fc 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMLocking option processing on CPU with rtm support and * on VM with rtm-locking support. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMLockingOptionOnSupportedConfig diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java index 295a7f46e46..dd6ac2d406b 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMLocking option processing on CPU without * rtm support. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMLockingOptionOnUnsupportedCPU diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java index 0489add80b5..e257f3451a1 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMLocking option processing on CPU with rtm support * in case when VM should not support this option. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMLockingOptionOnUnsupportedVM diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java index 3bc2ddca448..f6128654509 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify processing of UseRTMLocking and UseBiasedLocking * options combination on CPU and VM with rtm support. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMLockingOptionWithBiasedLocking diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java index a49b3755a4c..a03ba37ace1 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMAbortRatio affects amount of aborts before * deoptimization. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMAbortRatio diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java b/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java index ac194ca3550..d76e812530d 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMAbortThreshold option affects * amount of aborts after which abort ratio is calculated. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMAbortThreshold diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java index 75042ee7753..91b7bafe142 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java @@ -29,7 +29,7 @@ * caused by reason other then rtm_state_change will reset * method's RTM state. And if we don't use RTMDeopt, then * RTM state remain the same after such deoptimization. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMAfterNonRTMDeopt diff --git a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java index 0c5f1ad90b5..3dccdd911af 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that on high abort ratio method will be recompiled * without rtm locking. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMDeoptOnHighAbortRatio diff --git a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java index 9567e3e5277..1a62cfd5149 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java @@ -26,7 +26,7 @@ * @test * @bug 8031320 * @summary Verify that on low abort ratio method will be recompiled. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMDeoptOnLowAbortRatio diff --git a/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java b/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java index 57181e314e5..56ab0937c0b 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMLockingCalculationDelay affect when * abort ratio calculation is started. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMLockingCalculationDelay diff --git a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java index 7d8d44e5211..56fb6bef993 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMLockingThreshold affects rtm state transition * ProfileRTM => UseRTM. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMLockingThreshold diff --git a/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java b/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java index ef4de42ca7b..4a51463e01d 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java @@ -26,7 +26,7 @@ * @test * @bug 8031320 * @summary Verify that RTMRetryCount affects actual amount of retries. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMRetryCount diff --git a/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java b/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java index 0393a15a8dd..30abc3b187a 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMSpinLoopCount affects time spent * between locking attempts. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMSpinLoopCount diff --git a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java index 15ff5b380ea..3b9b9fcea65 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMTotalCountIncrRate option affects * RTM locking statistics. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestRTMTotalCountIncrRate diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java index 3fc896a2f42..a41535c7f75 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that rtm locking is used for stack locks before * inflation and after it used for inflated locks. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMAfterLockInflation diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java b/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java index 02f693563e9..b7cd4bf83f3 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that UseRTMDeopt affects uncommon trap installation in * copmpiled methods with synchronized block. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMDeopt diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java b/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java index 96b74c403cd..727e165cdac 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java @@ -26,7 +26,7 @@ * @test * @bug 8031320 * @summary Verify that rtm locking is used for inflated locks. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMForInflatedLocks diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java b/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java index 818a6c93ca0..b6f301dc1de 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java @@ -26,7 +26,7 @@ * @test * @bug 8031320 * @summary Verify that rtm locking is used for stack locks. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMForStackLocks diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java b/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java index 0a8906bb193..0d7e788c72f 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that UseRTMXendForLockBusy option affects * method behaviour if lock is busy. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMXendForLockBusy diff --git a/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java b/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java index 95993f661c5..a14aa9d882e 100644 --- a/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java +++ b/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that NoRTMLockEliding option could be applied to * specified method and that such method will not use rtm. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestNoRTMLockElidingOption diff --git a/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java b/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java index 6db0107cdc5..acb03abd104 100644 --- a/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java +++ b/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java @@ -28,7 +28,7 @@ * @summary Verify that UseRTMLockEliding option could be applied to * specified method and that such method will not be deoptimized * on high abort ratio. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestUseRTMLockElidingOption diff --git a/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java index e8f63e7ae7e..6accb0cb607 100644 --- a/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java +++ b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java @@ -29,7 +29,7 @@ * on overall aborts and locks count and count of aborts of * different types. Test also verify that VM output does not * contain rtm locking statistics when it should not. - * @library /testlibrary /../../test/lib /compiler/testlibrary + * @library /testlibrary /test/lib /compiler/testlibrary * @modules java.base/sun.misc * java.management * @build TestPrintPreciseRTMLockingStatistics diff --git a/hotspot/test/compiler/runtime/8010927/Test8010927.java b/hotspot/test/compiler/runtime/8010927/Test8010927.java index c00e81415c8..35317801f7f 100644 --- a/hotspot/test/compiler/runtime/8010927/Test8010927.java +++ b/hotspot/test/compiler/runtime/8010927/Test8010927.java @@ -25,7 +25,7 @@ * @test * @bug 8010927 * @summary Kitchensink crashed with SIGSEGV, Problematic frame: v ~StubRoutines::checkcast_arraycopy - * @library /../../test/lib /testlibrary + * @library /test/lib /testlibrary * @modules java.base/sun.misc * @build Test8010927 * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/stable/TestStableBoolean.java b/hotspot/test/compiler/stable/TestStableBoolean.java index 9a01ec74238..767055752b1 100644 --- a/hotspot/test/compiler/stable/TestStableBoolean.java +++ b/hotspot/test/compiler/stable/TestStableBoolean.java @@ -26,7 +26,7 @@ /* * @test TestStableBoolean * @summary tests on stable fields and arrays - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestStableBoolean StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableByte.java b/hotspot/test/compiler/stable/TestStableByte.java index de49894d06f..9201cd09794 100644 --- a/hotspot/test/compiler/stable/TestStableByte.java +++ b/hotspot/test/compiler/stable/TestStableByte.java @@ -26,7 +26,7 @@ /* * @test TestStableByte * @summary tests on stable fields and arrays - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestStableByte StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableChar.java b/hotspot/test/compiler/stable/TestStableChar.java index fa5a642e1f1..f1a2e9f5842 100644 --- a/hotspot/test/compiler/stable/TestStableChar.java +++ b/hotspot/test/compiler/stable/TestStableChar.java @@ -26,7 +26,7 @@ /* * @test TestStableChar * @summary tests on stable fields and arrays - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestStableChar StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableDouble.java b/hotspot/test/compiler/stable/TestStableDouble.java index 98a7128ea07..54ff453cd66 100644 --- a/hotspot/test/compiler/stable/TestStableDouble.java +++ b/hotspot/test/compiler/stable/TestStableDouble.java @@ -26,7 +26,7 @@ /* * @test TestStableDouble * @summary tests on stable fields and arrays - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestStableDouble StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableFloat.java b/hotspot/test/compiler/stable/TestStableFloat.java index 13ad90ced19..00a90591092 100644 --- a/hotspot/test/compiler/stable/TestStableFloat.java +++ b/hotspot/test/compiler/stable/TestStableFloat.java @@ -26,7 +26,7 @@ /* * @test TestStableFloat * @summary tests on stable fields and arrays - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestStableFloat StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableInt.java b/hotspot/test/compiler/stable/TestStableInt.java index 55ab13da1c7..5a052a15dec 100644 --- a/hotspot/test/compiler/stable/TestStableInt.java +++ b/hotspot/test/compiler/stable/TestStableInt.java @@ -26,7 +26,7 @@ /* * @test TestStableInt * @summary tests on stable fields and arrays - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestStableInt StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableLong.java b/hotspot/test/compiler/stable/TestStableLong.java index 4b6c574f33b..a859a6b20d7 100644 --- a/hotspot/test/compiler/stable/TestStableLong.java +++ b/hotspot/test/compiler/stable/TestStableLong.java @@ -26,7 +26,7 @@ /* * @test TestStableLong * @summary tests on stable fields and arrays - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestStableLong StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableObject.java b/hotspot/test/compiler/stable/TestStableObject.java index 19fef93ce28..38b8c1ce9df 100644 --- a/hotspot/test/compiler/stable/TestStableObject.java +++ b/hotspot/test/compiler/stable/TestStableObject.java @@ -26,7 +26,7 @@ /* * @test TestStableObject * @summary tests on stable fields and arrays - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestStableObject StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableShort.java b/hotspot/test/compiler/stable/TestStableShort.java index 20b65cfda3c..57e52cfa0d4 100644 --- a/hotspot/test/compiler/stable/TestStableShort.java +++ b/hotspot/test/compiler/stable/TestStableShort.java @@ -26,7 +26,7 @@ /* * @test TestStableShort * @summary tests on stable fields and arrays - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build TestStableShort StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/tiered/ConstantGettersTransitionsTest.java b/hotspot/test/compiler/tiered/ConstantGettersTransitionsTest.java index 3b3271d2938..8220f10229f 100644 --- a/hotspot/test/compiler/tiered/ConstantGettersTransitionsTest.java +++ b/hotspot/test/compiler/tiered/ConstantGettersTransitionsTest.java @@ -26,7 +26,7 @@ import java.util.concurrent.Callable; /** * @test ConstantGettersTransitionsTest - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * @modules java.base/sun.misc * java.management * @build TransitionsTestExecutor ConstantGettersTransitionsTest diff --git a/hotspot/test/compiler/tiered/LevelTransitionTest.java b/hotspot/test/compiler/tiered/LevelTransitionTest.java index 26236ea8542..be67394d9e7 100644 --- a/hotspot/test/compiler/tiered/LevelTransitionTest.java +++ b/hotspot/test/compiler/tiered/LevelTransitionTest.java @@ -28,7 +28,7 @@ import java.util.concurrent.Callable; /** * @test LevelTransitionTest - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * @modules java.base/sun.misc * java.management * @ignore 8067651 diff --git a/hotspot/test/compiler/tiered/NonTieredLevelsTest.java b/hotspot/test/compiler/tiered/NonTieredLevelsTest.java index 510d7f6ae47..a3596c3b1f0 100644 --- a/hotspot/test/compiler/tiered/NonTieredLevelsTest.java +++ b/hotspot/test/compiler/tiered/NonTieredLevelsTest.java @@ -25,7 +25,7 @@ import java.util.function.IntPredicate; /** * @test NonTieredLevelsTest - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * @modules java.management * @build NonTieredLevelsTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/tiered/TieredLevelsTest.java b/hotspot/test/compiler/tiered/TieredLevelsTest.java index 92c65c0af59..74158e3fe86 100644 --- a/hotspot/test/compiler/tiered/TieredLevelsTest.java +++ b/hotspot/test/compiler/tiered/TieredLevelsTest.java @@ -23,7 +23,7 @@ /** * @test TieredLevelsTest - * @library /testlibrary /../../test/lib /compiler/whitebox + * @library /testlibrary /test/lib /compiler/whitebox * @modules java.management * @build TieredLevelsTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/types/correctness/CorrectnessTest.java b/hotspot/test/compiler/types/correctness/CorrectnessTest.java index 7eb8e099e37..448e974b875 100644 --- a/hotspot/test/compiler/types/correctness/CorrectnessTest.java +++ b/hotspot/test/compiler/types/correctness/CorrectnessTest.java @@ -24,7 +24,7 @@ /* * @test CorrectnessTest * @bug 8038418 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @ignore 8066173 diff --git a/hotspot/test/compiler/types/correctness/OffTest.java b/hotspot/test/compiler/types/correctness/OffTest.java index e25c3b71bbf..b0ee53542ad 100644 --- a/hotspot/test/compiler/types/correctness/OffTest.java +++ b/hotspot/test/compiler/types/correctness/OffTest.java @@ -24,7 +24,7 @@ /* * @test CorrectnessTest * @bug 8038418 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @ignore 8066173 diff --git a/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java b/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java index 63db9ba2d4e..50979d260c6 100644 --- a/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java +++ b/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java @@ -27,7 +27,7 @@ import java.lang.reflect.Method; /* * @test * @bug 8009761 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @summary Deoptimization on sparc doesn't set Llast_SP correctly in the interpreter frames it creates * @build Test8009761 * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java b/hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java index 61143c77777..14e46af1e19 100644 --- a/hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java +++ b/hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java @@ -40,7 +40,7 @@ import uncommontrap.Verifier; /* * @test * @bug 8030976 8059226 - * @library /testlibrary /compiler/testlibrary /../../test/lib + * @library /testlibrary /compiler/testlibrary /test/lib * @modules java.base/jdk.internal.org.objectweb.asm * java.base/sun.misc * java.compiler diff --git a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java index 110c9dfb22c..bd2b28db674 100644 --- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java +++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java @@ -26,7 +26,7 @@ /* * @test * @summary tests on constant folding of unsafe get operations - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions * -Xbatch -XX:-TieredCompilation * -XX:+FoldStableValues @@ -43,13 +43,13 @@ package java.lang.invoke; import jdk.internal.org.objectweb.asm.*; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static jdk.internal.org.objectweb.asm.Opcodes.*; public class UnsafeGetConstantField { static final Class THIS_CLASS = UnsafeGetConstantField.class; - static final Unsafe U = Utils.getUnsafe(); + static final Unsafe U = Unsafe.getUnsafe(); public static void main(String[] args) { testUnsafeGetAddress(); diff --git a/hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java b/hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java index 7f0e33171ee..9f8e9d38fc4 100644 --- a/hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java +++ b/hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java @@ -34,7 +34,7 @@ import jdk.test.lib.InfiniteLoop; /* * @test AllocationCodeBlobTest * @bug 8059624 8064669 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build AllocationCodeBlobTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/ClearMethodStateTest.java b/hotspot/test/compiler/whitebox/ClearMethodStateTest.java index be2cbdd2300..63a0ec53e8c 100644 --- a/hotspot/test/compiler/whitebox/ClearMethodStateTest.java +++ b/hotspot/test/compiler/whitebox/ClearMethodStateTest.java @@ -26,7 +26,7 @@ import java.util.function.Function; /* * @test ClearMethodStateTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build ClearMethodStateTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java b/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java index 90169717ab3..d66e60dd6d2 100644 --- a/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java +++ b/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java @@ -24,7 +24,7 @@ /* * @test DeoptimizeAllTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build DeoptimizeAllTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java b/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java index c7596c797c0..c13a3814ac3 100644 --- a/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java +++ b/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java @@ -24,7 +24,7 @@ /* * @test DeoptimizeFramesTest * @bug 8028595 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build DeoptimizeFramesTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java b/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java index 3b08717b20a..bbd34105cd8 100644 --- a/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java +++ b/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java @@ -24,7 +24,7 @@ /* * @test DeoptimizeMethodTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build DeoptimizeMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java b/hotspot/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java index 54851c4d61d..54dfe6312ee 100644 --- a/hotspot/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java +++ b/hotspot/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java @@ -28,7 +28,7 @@ import java.lang.reflect.Method; /* * @test DeoptimizeMultipleOSRTest * @bug 8061817 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build DeoptimizeMultipleOSRTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java b/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java index 2560d81fc30..77323900077 100644 --- a/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java +++ b/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java @@ -24,7 +24,7 @@ /* * @test EnqueueMethodForCompilationTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build EnqueueMethodForCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java index 742805827da..64918100a19 100644 --- a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java +++ b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java @@ -34,7 +34,7 @@ import jdk.test.lib.InfiniteLoop; /* * @test * @bug 8059624 8064669 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build ForceNMethodSweepTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java b/hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java index 29f0dd9781f..963258545bc 100644 --- a/hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java +++ b/hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java @@ -33,7 +33,7 @@ import jdk.test.lib.Asserts; /* * @test GetCodeHeapEntriesTest * @bug 8059624 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build GetCodeHeapEntriesTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/GetNMethodTest.java b/hotspot/test/compiler/whitebox/GetNMethodTest.java index 400852f6114..229f031d32e 100644 --- a/hotspot/test/compiler/whitebox/GetNMethodTest.java +++ b/hotspot/test/compiler/whitebox/GetNMethodTest.java @@ -29,7 +29,7 @@ import jdk.test.lib.Asserts; /* * @test GetNMethodTest * @bug 8038240 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build GetNMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java b/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java index 9b22967f6fb..fec015193d2 100644 --- a/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java +++ b/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java @@ -24,7 +24,7 @@ /* * @test IsMethodCompilableTest * @bug 8007270 8006683 8007288 8022832 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build jdk.test.lib.* sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/LockCompilationTest.java b/hotspot/test/compiler/whitebox/LockCompilationTest.java index 60703f04dcd..93a1837730d 100644 --- a/hotspot/test/compiler/whitebox/LockCompilationTest.java +++ b/hotspot/test/compiler/whitebox/LockCompilationTest.java @@ -24,7 +24,7 @@ /* * @test LockCompilationTest * @bug 8059624 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build LockCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java index faac33515d4..e9b808d3620 100644 --- a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java +++ b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java @@ -24,7 +24,7 @@ /* * @test MakeMethodNotCompilableTest * @bug 8012322 8006683 8007288 8022832 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build MakeMethodNotCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java b/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java index 1638a5eff28..322074baa3a 100644 --- a/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java +++ b/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java @@ -24,7 +24,7 @@ /* * @test SetDontInlineMethodTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build SetDontInlineMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java b/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java index a9e19915927..1720e93e673 100644 --- a/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java +++ b/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java @@ -24,7 +24,7 @@ /* * @test SetForceInlineMethodTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build SetForceInlineMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/gc/CondCardMark/Basic.java b/hotspot/test/gc/CondCardMark/Basic.java index b9b3e775710..f936ce88210 100644 --- a/hotspot/test/gc/CondCardMark/Basic.java +++ b/hotspot/test/gc/CondCardMark/Basic.java @@ -26,7 +26,7 @@ * @bug 8076987 * @bug 8078438 * @summary Verify UseCondCardMark works - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build Basic * @run main/othervm -Xint Basic * @run main/othervm -Xint -XX:+UseCondCardMark Basic diff --git a/hotspot/test/gc/TestSmallHeap.java b/hotspot/test/gc/TestSmallHeap.java index 23c1b00a9c3..1289046edba 100644 --- a/hotspot/test/gc/TestSmallHeap.java +++ b/hotspot/test/gc/TestSmallHeap.java @@ -29,7 +29,7 @@ * @requires vm.compMode != "Xcomp" * @requires vm.opt.UseCompressedOops != false * @summary Verify that starting the VM with a small heap works - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management/sun.management * @build TestSmallHeap * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java b/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java index b2b017b0ffe..2d294c7e666 100644 --- a/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java +++ b/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java @@ -26,7 +26,7 @@ * @key gc * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the CMS collector - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestCMSHeapSizeFlags TestMaxHeapSizeTools diff --git a/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java b/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java index 32c55bddb63..fa6ffe6049f 100644 --- a/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java +++ b/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java @@ -26,7 +26,7 @@ * @key gc * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the G1 collector - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestG1HeapSizeFlags TestMaxHeapSizeTools diff --git a/hotspot/test/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java b/hotspot/test/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java index b53ae67303f..9ae68929c2e 100644 --- a/hotspot/test/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java +++ b/hotspot/test/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java @@ -25,7 +25,7 @@ * @test TestMinAndInitialSurvivorRatioFlags * @key gc * @summary Verify that MinSurvivorRatio and InitialSurvivorRatio flags work - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestMinAndInitialSurvivorRatioFlags diff --git a/hotspot/test/gc/arguments/TestMinInitialErgonomics.java b/hotspot/test/gc/arguments/TestMinInitialErgonomics.java index 3310411f163..680887c1d00 100644 --- a/hotspot/test/gc/arguments/TestMinInitialErgonomics.java +++ b/hotspot/test/gc/arguments/TestMinInitialErgonomics.java @@ -26,7 +26,7 @@ * @key gc * @bug 8006088 * @summary Test ergonomics decisions related to minimum and initial heap size. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestMinInitialErgonomics TestMaxHeapSizeTools diff --git a/hotspot/test/gc/arguments/TestNewRatioFlag.java b/hotspot/test/gc/arguments/TestNewRatioFlag.java index c4f947a43dd..4bcfce02e1b 100644 --- a/hotspot/test/gc/arguments/TestNewRatioFlag.java +++ b/hotspot/test/gc/arguments/TestNewRatioFlag.java @@ -26,7 +26,7 @@ * @key gc * @bug 8025166 * @summary Verify that heap devided among generations according to NewRatio - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestNewRatioFlag diff --git a/hotspot/test/gc/arguments/TestNewSizeFlags.java b/hotspot/test/gc/arguments/TestNewSizeFlags.java index 83819944983..84c027e6275 100644 --- a/hotspot/test/gc/arguments/TestNewSizeFlags.java +++ b/hotspot/test/gc/arguments/TestNewSizeFlags.java @@ -26,7 +26,7 @@ * @key gc * @bug 8025166 * @summary Verify that young gen size conforms values specified by NewSize, MaxNewSize and Xmn options - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestNewSizeFlags diff --git a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java index fa12fa133a2..0576979b718 100644 --- a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java +++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java @@ -27,7 +27,7 @@ * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the * parallel collectors. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestParallelHeapSizeFlags TestMaxHeapSizeTools diff --git a/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java b/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java index f5e320e0400..b52b08c6cc4 100644 --- a/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java +++ b/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java @@ -26,7 +26,7 @@ * @key gc * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the Serial collector - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestSerialHeapSizeFlags TestMaxHeapSizeTools diff --git a/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java b/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java index 1d41144510b..ce20f3db9a3 100644 --- a/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java +++ b/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java @@ -25,7 +25,7 @@ * @test TestSurvivorRatioFlag * @key gc * @summary Verify that actual survivor ratio is equal to specified SurvivorRatio value - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestSurvivorRatioFlag diff --git a/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java b/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java index 4288e579acb..a9d8a984d0b 100644 --- a/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java +++ b/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java @@ -25,7 +25,7 @@ * @test TestTargetSurvivorRatioFlag * @key gc * @summary Verify that option TargetSurvivorRatio affects survivor space occupancy after minor GC. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestTargetSurvivorRatioFlag diff --git a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java index 5a2005e643c..64b5129122c 100644 --- a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java +++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java @@ -26,7 +26,7 @@ * @key gc * @bug 8010722 * @summary Tests ergonomics for UseCompressedOops. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management/sun.management * @build TestUseCompressedOopsErgo TestUseCompressedOopsErgoTools diff --git a/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java index a655cc6477c..634cc87edf5 100644 --- a/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java +++ b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java @@ -25,7 +25,7 @@ * @test * @key gc * @bug 8049831 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestCMSClassUnloadingEnabledHWM diff --git a/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java index 2a9abf285b5..8637e6f4b9c 100644 --- a/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java +++ b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java @@ -25,7 +25,7 @@ * @test * @key gc * @bug 8049831 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestG1ClassUnloadingHWM diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java index 4103c9d18fe..0dfe7ac0b3d 100644 --- a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java +++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java @@ -121,6 +121,7 @@ public class TestEagerReclaimHumongousRegionsClearMarkBits { "-XX:G1HeapRegionSize=1M", "-XX:InitiatingHeapOccupancyPercent=0", // Want to have as much as possible initial marks. "-XX:+PrintGC", + "-XX:+UnlockDiagnosticVMOptions", "-XX:+VerifyAfterGC", "-XX:ConcGCThreads=1", // Want to make marking as slow as possible. "-XX:+IgnoreUnrecognizedVMOptions", // G1VerifyBitmaps is develop only. diff --git a/hotspot/test/gc/g1/TestGCLogMessages.java b/hotspot/test/gc/g1/TestGCLogMessages.java index 380d89a46a9..ec5b87d3081 100644 --- a/hotspot/test/gc/g1/TestGCLogMessages.java +++ b/hotspot/test/gc/g1/TestGCLogMessages.java @@ -79,6 +79,7 @@ public class TestGCLogMessages { // Misc Top-level new LogMessageWithLevel("Code Root Purge", Level.FINER), new LogMessageWithLevel("String Dedup Fixup", Level.FINER), + new LogMessageWithLevel("Expand Heap After Collection", Level.FINER), // Free CSet new LogMessageWithLevel("Young Free CSet", Level.FINEST), new LogMessageWithLevel("Non-Young Free CSet", Level.FINEST), diff --git a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java index 6d830478a20..5f2e6fb918a 100644 --- a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java +++ b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java @@ -26,7 +26,7 @@ * @key regression * @key gc * @bug 8027756 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestHumongousCodeCacheRoots diff --git a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java index 326f23fbee0..03d214d19ec 100644 --- a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java +++ b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java @@ -26,13 +26,13 @@ * @summary Test that auxiliary data structures are allocated using large pages if available. * @bug 8058354 8079208 * @key gc - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @requires (vm.gc=="G1" | vm.gc=="null") * @build jdk.test.lib.* sun.hotspot.WhiteBox * @build TestLargePageUseForAuxMemory * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm -Xbootclasspath/a:. -XX:+UseG1GC -XX:+WhiteBoxAPI -XX:+IgnoreUnrecognizedVMOptions -XX:+UseLargePages TestLargePageUseForAuxMemory + * @run main/othervm -Xbootclasspath/a:. -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+IgnoreUnrecognizedVMOptions -XX:+UseLargePages TestLargePageUseForAuxMemory */ import java.lang.Math; diff --git a/hotspot/test/gc/g1/TestPLABOutput.java b/hotspot/test/gc/g1/TestPLABOutput.java new file mode 100644 index 00000000000..7c60731d4f1 --- /dev/null +++ b/hotspot/test/gc/g1/TestPLABOutput.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015, 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 TestPLABOutput + * @bug 8140585 + * @summary Check that G1 does not report empty PLAB statistics in the first evacuation. + * @requires vm.gc=="G1" | vm.gc=="null" + * @key gc + * @library /testlibrary /../../test/lib + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver TestPLABOutput + */ + +import sun.hotspot.WhiteBox; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.ProcessTools; + +import static jdk.test.lib.Asserts.*; + +public class TestPLABOutput { + + public static void runTest() throws Exception { + final String[] arguments = { + "-Xbootclasspath/a:.", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:+UseG1GC", + "-Xmx10M", + "-XX:+PrintGC", + "-XX:+PrintPLAB", + GCTest.class.getName() + }; + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(arguments); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + output.shouldHaveExitValue(0); + + System.out.println(output.getStdout()); + + String pattern = "#0:.*allocated = (\\d+).*"; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(output.getStdout()); + + if (!m.find()) { + throw new RuntimeException("Could not find any PLAB statistics output"); + } + int allocated = Integer.parseInt(m.group(1)); + assertGT(allocated, 0, "Did not allocate any memory during test"); + } + + public static void main(String[] args) throws Exception { + runTest(); + } + + static class GCTest { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + public static Object holder; + + public static void main(String [] args) { + holder = new byte[100]; + WB.youngGC(); + System.out.println(holder); + } + } +} + diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java index b6d0800fcf2..b2bbceaa34b 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build jdk.test.lib.* sun.hotspot.WhiteBox diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java index a5b0f0bb77b..e87adfe3648 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build jdk.test.lib.* sun.hotspot.WhiteBox diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java index cf934f1e6ea..630172fd201 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build jdk.test.lib.* sun.hotspot.WhiteBox diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java index 6db6aee0179..e101d9e865b 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build jdk.test.lib.* sun.hotspot.WhiteBox diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java index e790a7fbd33..1a7a46e03a6 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build jdk.test.lib.* sun.hotspot.WhiteBox diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java index c7098c13c0b..9fd18119243 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build jdk.test.lib.* sun.hotspot.WhiteBox diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java index 44ecc131d40..ac24ad698b5 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build jdk.test.lib.* sun.hotspot.WhiteBox diff --git a/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java index ac632e53fe6..f372459987c 100644 --- a/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java +++ b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java @@ -31,7 +31,7 @@ import sun.hotspot.WhiteBox; * @test TestHumongousThreshold * @summary Checks that objects larger than half a region are allocated as humongous * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management * @build sun.hotspot.WhiteBox * gc.g1.humongousObjects.Helpers diff --git a/hotspot/test/gc/g1/mixedgc/TestLogging.java b/hotspot/test/gc/g1/mixedgc/TestLogging.java index 7d3dc69aa4b..7e1ce49e642 100644 --- a/hotspot/test/gc/g1/mixedgc/TestLogging.java +++ b/hotspot/test/gc/g1/mixedgc/TestLogging.java @@ -25,7 +25,7 @@ * @test TestLogging * @summary Check that a mixed GC is reflected in the gc logs * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @ignore 8138607 * @modules java.management * @build sun.hotspot.WhiteBox gc.g1.mixedgc.TestLogging diff --git a/hotspot/test/gc/metaspace/TestCapacityUntilGCWrapAround.java b/hotspot/test/gc/metaspace/TestCapacityUntilGCWrapAround.java index af7d10fe70e..be4ad861253 100644 --- a/hotspot/test/gc/metaspace/TestCapacityUntilGCWrapAround.java +++ b/hotspot/test/gc/metaspace/TestCapacityUntilGCWrapAround.java @@ -25,7 +25,7 @@ * @test * @key gc * @bug 8049831 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestCapacityUntilGCWrapAround diff --git a/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java b/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java index 46a9c9211dc..5cc7efaeb95 100644 --- a/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java +++ b/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that object's alignment in eden space is not affected by * SurvivorAlignmentInBytes option. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestAllocationInEden SurvivorAlignmentTestMain AlignmentHelper diff --git a/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java b/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java index 80f29d02b28..b8d276367eb 100644 --- a/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java +++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that objects promoted from eden space to tenured space during * full GC are not aligned to SurvivorAlignmentInBytes value. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestPromotionFromEdenToTenured SurvivorAlignmentTestMain diff --git a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java index f8662c87683..06aaf43c027 100644 --- a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java +++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that objects promoted from survivor space to tenured space * during full GC are not aligned to SurvivorAlignmentInBytes value. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestPromotionFromSurvivorToTenuredAfterFullGC diff --git a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java index 28ad6e99046..c0ce4d65701 100644 --- a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java +++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java @@ -27,7 +27,7 @@ * @summary Verify that objects promoted from survivor space to tenured space * when their age exceeded tenuring threshold are not aligned to * SurvivorAlignmentInBytes value. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestPromotionFromSurvivorToTenuredAfterMinorGC diff --git a/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java b/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java index 18d58a7b001..42e70dccc84 100644 --- a/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java +++ b/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that objects promoted from eden space to survivor space after * minor GC are aligned to SurvivorAlignmentInBytes. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestPromotionToSurvivor diff --git a/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java b/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java index b90f7680486..fe2e64c17ea 100644 --- a/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java +++ b/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java @@ -25,7 +25,7 @@ * @test TestConMarkCycleWB * @bug 8065579 * @requires vm.gc=="null" | vm.gc=="G1" - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.compiler * java.management diff --git a/hotspot/test/gc/whitebox/TestWBGC.java b/hotspot/test/gc/whitebox/TestWBGC.java index 13e64100c1f..707edbd8386 100644 --- a/hotspot/test/gc/whitebox/TestWBGC.java +++ b/hotspot/test/gc/whitebox/TestWBGC.java @@ -25,7 +25,7 @@ * @test TestWBGC * @bug 8055098 * @summary Test verify that WB methods isObjectInOldGen and youngGC works correctly. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestWBGC diff --git a/hotspot/test/runtime/Annotations/TestAnnotatedStringEncoding.java b/hotspot/test/runtime/Annotations/TestAnnotatedStringEncoding.java new file mode 100644 index 00000000000..ed89c00fea4 --- /dev/null +++ b/hotspot/test/runtime/Annotations/TestAnnotatedStringEncoding.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2015, 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. + */ + +import java.lang.annotation.*; +import java.lang.reflect.*; + +/* + * @test + * @bug 8054307 + * @summary Tests the correct encoding of latin1/UTF16 Strings used in annotations. + */ +public class TestAnnotatedStringEncoding { + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + @interface Test { + String str(); + int index(); + } + + public static void main(String[] args) throws Exception { + new TestAnnotatedStringEncoding().run(); + } + + public void run() { + // Iterate over annotated methods and retrieve the string + for (Method m : this.getClass().getMethods()) { + if (m.isAnnotationPresent(Test.class)) { + // Check if string equals expected value + Test test = m.getAnnotation(Test.class); + String str = test.str(); + int index = test.index(); + if (!str.equals(strValue[index])) { + throw new RuntimeException(m.getName() + " failed: \"" + str + "\" (0x" + Integer.toHexString(str.charAt(0)) + + ") does not equal \"" + strValue[index] + "\" (0x" + Integer.toHexString(strValue[index].charAt(0)) + ") ."); + } + } + } + System.out.println("Test passed."); + } + + public static String[] strValue = { + "\u0000", "\u0020", "\u0021", "\u0080", + "\u00FF", "\u0100", "\u017F", "\u01FF", + "\u07FF", "\u0800", "\uC280", "\uC2BF", + "\uC380", "\uC3BF", "\uC5BF", "\uFFFF", + "\u10000", "\u1FFFFF", "\u200000", + "\u3FFFFFF", "\u4000000", "\u7FFFFFFF", + "ab\uff23\uff24ef\uff27", "\uff21\uff22cd\uff25g", "\u00FF\u00FF\u00FF", "\u00A1\u00A1\u00A1\u00A1", ""}; + + @Test(str = "\u0000", index = 0) + public static void check0() { } + + @Test(str = "\u0020", index = 1) + public static void check1() { } + + @Test(str = "\u0021", index = 2) + public static void check2() { } + + @Test(str = "\u0080", index = 3) + public static void check3() { } + + @Test(str = "\u00FF", index = 4) + public static void check4() { } + + @Test(str = "\u0100", index = 5) + public static void check5() { } + + @Test(str = "\u017F", index = 6) + public static void check6() { } + + @Test(str = "\u01FF", index = 7) + public static void check7() { } + + @Test(str = "\u07FF", index = 8) + public static void check8() { } + + @Test(str = "\u0800", index = 9) + public static void check9() { } + + @Test(str = "\uC280", index = 10) + public static void check10() { } + + @Test(str = "\uC2BF", index = 11) + public static void check11() { } + + @Test(str = "\uC380", index = 12) + public static void check12() { } + + @Test(str = "\uC3BF", index = 13) + public static void check13() { } + + @Test(str = "\uC5BF", index = 14) + public static void check14() { } + + @Test(str = "\uFFFF", index = 15) + public static void check15() { } + + @Test(str = "\u10000", index = 16) + public static void check16() { } + + @Test(str = "\u1FFFFF", index = 17) + public static void check17() { } + + @Test(str = "\u200000", index = 18) + public static void check18() { } + + @Test(str = "\u3FFFFFF", index = 19) + public static void check19() { } + + @Test(str = "\u4000000", index = 20) + public static void check20() { } + + @Test(str = "\u7FFFFFFF", index = 21) + public static void check21() { } + + @Test(str = "ab\uff23\uff24ef\uff27", index = 22) + public static void check22() { } + + @Test(str = "\uff21\uff22cd\uff25g", index = 23) + public static void check23() { } + + @Test(str = "\u00FF\u00FF\u00FF", index = 24) + public static void check24() { } + + @Test(str = "\u00A1\u00A1\u00A1\u00A1", index = 25) + public static void check25() { } + + @Test(str = "", index = 26) + public static void check26() { } +} diff --git a/hotspot/test/runtime/ClassUnload/KeepAliveClass.java b/hotspot/test/runtime/ClassUnload/KeepAliveClass.java index 8bac5b7a464..a1080269447 100644 --- a/hotspot/test/runtime/ClassUnload/KeepAliveClass.java +++ b/hotspot/test/runtime/ClassUnload/KeepAliveClass.java @@ -24,7 +24,7 @@ /* * @test KeepAliveClass * @summary This test case uses a java.lang.Class instance to keep a class alive. - * @library /testlibrary /../../test/lib /runtime/testlibrary + * @library /testlibrary /test/lib /runtime/testlibrary * @library classes * @build KeepAliveClass test.Empty * @build ClassUnloadCommon diff --git a/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java b/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java index 5bd4431f046..21e92a108f2 100644 --- a/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java +++ b/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java @@ -24,7 +24,7 @@ /* * @test KeepAliveClassLoader * @summary This test case uses a java.lang.ClassLoader instance to keep a class alive. - * @library /testlibrary /../../test/lib /runtime/testlibrary + * @library /testlibrary /test/lib /runtime/testlibrary * @library classes * @build KeepAliveClassLoader test.Empty * @build ClassUnloadCommon diff --git a/hotspot/test/runtime/ClassUnload/KeepAliveObject.java b/hotspot/test/runtime/ClassUnload/KeepAliveObject.java index 1e4126cb5ff..4a8ffb70000 100644 --- a/hotspot/test/runtime/ClassUnload/KeepAliveObject.java +++ b/hotspot/test/runtime/ClassUnload/KeepAliveObject.java @@ -24,7 +24,7 @@ /* * @test KeepAliveObject * @summary This test case uses a class instance to keep the class alive. - * @library /testlibrary /../../test/lib /runtime/testlibrary + * @library /testlibrary /test/lib /runtime/testlibrary * @library classes * @build KeepAliveObject test.Empty * @build ClassUnloadCommon diff --git a/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java b/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java index ae261768149..0aa3547fc3f 100644 --- a/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java +++ b/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java @@ -24,7 +24,7 @@ /* * @test KeepAliveSoftReference * @summary This test case uses a java.lang.ref.SoftReference referencing a class instance to keep a class alive. - * @library /testlibrary /../../test/lib /runtime/testlibrary + * @library /testlibrary /test/lib /runtime/testlibrary * @library classes * @build KeepAliveSoftReference test.Empty * @build ClassUnloadCommon diff --git a/hotspot/test/runtime/ClassUnload/UnloadTest.java b/hotspot/test/runtime/ClassUnload/UnloadTest.java index 452155e3e2c..cb8f0526329 100644 --- a/hotspot/test/runtime/ClassUnload/UnloadTest.java +++ b/hotspot/test/runtime/ClassUnload/UnloadTest.java @@ -23,7 +23,7 @@ /* * @test UnloadTest - * @library /runtime/testlibrary /testlibrary /../../test/lib + * @library /runtime/testlibrary /testlibrary /test/lib * @library classes * @build ClassUnloadCommon test.Empty * @build UnloadTest diff --git a/hotspot/test/runtime/CommandLine/IgnoreUnrecognizedVMOptions.java b/hotspot/test/runtime/CommandLine/IgnoreUnrecognizedVMOptions.java new file mode 100644 index 00000000000..c876b136969 --- /dev/null +++ b/hotspot/test/runtime/CommandLine/IgnoreUnrecognizedVMOptions.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015, 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. + */ + +import jdk.test.lib.*; + +/* + * @test + * @bug 8129855 + * @summary -XX:+IgnoreUnrecognizedVMOptions should work according to the spec from JDK-8129855 + * + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @run main IgnoreUnrecognizedVMOptions + */ +public class IgnoreUnrecognizedVMOptions { + + private static void runJavaAndCheckExitValue(boolean shouldSucceed, String... args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + if (shouldSucceed) { + output.shouldHaveExitValue(0); + } else { + output.shouldHaveExitValue(1); + } + } + + public static void main(String[] args) throws Exception { + boolean product = !Platform.isDebugBuild(); + + /* + #1.1 wrong value and non-existing flag: + exists, invalid value does not exist + -XX:MinHeapFreeRatio=notnum -XX:THIS_FLAG_DOESNT_EXIST + -IgnoreUnrecognizedVMOptions ERR ERR + +IgnoreUnrecognizedVMOptions ERR OK + */ + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:MinHeapFreeRatio=notnum", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:THIS_FLAG_DOESNT_EXIST", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:MinHeapFreeRatio=notnum", "-version"); + runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:THIS_FLAG_DOESNT_EXIST", "-version"); + + /* + #1.2 normal flag with ranges: + exists, in range exists, out of range + -XX:StackRedPages=1 -XX:StackRedPages=0 + -IgnoreUnrecognizedVMOptions OK ERR + +IgnoreUnrecognizedVMOptions OK ERR + */ + runJavaAndCheckExitValue(true, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:StackRedPages=1", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:StackRedPages=0", "-version"); + runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:StackRedPages=1", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:StackRedPages=0", "-version"); + + /* + #1.3 develop & notproduct flag on debug VM: + develop & !product_build notproduct & !product_build + -XX:+DeoptimizeALot -XX:+VerifyCodeCache + -IgnoreUnrecognizedVMOptions OK OK + +IgnoreUnrecognizedVMOptions OK OK + */ + if (!product) { + runJavaAndCheckExitValue(true, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:+DeoptimizeALot", "-version"); + runJavaAndCheckExitValue(true, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:+VerifyCodeCache", "-version"); + runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+DeoptimizeALot", "-version"); + runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+VerifyCodeCache", "-version"); + } + + /* + #1.4 develop & notproduct flag on product VM: + develop & !product_build notproduct & product_build + -XX:+DeoptimizeALot -XX:+VerifyCodeCache + -IgnoreUnrecognizedVMOptions ERR ERR + +IgnoreUnrecognizedVMOptions OK OK + */ + if (product) { + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:+DeoptimizeALot", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:+VerifyCodeCache", "-version"); + runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+DeoptimizeALot", "-version"); + runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+VerifyCodeCache", "-version"); + } + + + /* + #1.5 malformed develop & notproduct flag on debug VM: + develop & !product_build notproduct & !product_build + -XX:DeoptimizeALot -XX:VerifyCodeCache + -IgnoreUnrecognizedVMOptions ERR ERR + +IgnoreUnrecognizedVMOptions ERR ERR + */ + if (!product) { + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:DeoptimizeALot", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:VerifyCodeCache", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:DeoptimizeALot", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:VerifyCodeCache", "-version"); + } + + /* + #1.6 malformed develop & notproduct flag on product VM: + develop & !product_build notproduct & product_build + -XX:DeoptimizeALot -XX:VerifyCodeCache + -IgnoreUnrecognizedVMOptions ERR ERR + +IgnoreUnrecognizedVMOptions OK OK + */ + if (product) { + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:DeoptimizeALot", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:VerifyCodeCache", "-version"); + runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:DeoptimizeALot", "-version"); + runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:VerifyCodeCache", "-version"); + } + + /* + #1.7 locked flag: + diagnostic & locked experimental & locked commercial & locked + -XX:-UnlockDiagnosticVMOptions -XX:-UnlockExperimentalVMOptions -XX:-UnlockCommercialFeatures + -XX:+PrintInlining -XX:+AlwaysSafeConstructors -XX:+FlightRecorder + -IgnoreUnrecognizedVMOptions ERR ERR ERR + +IgnoreUnrecognizedVMOptions ERR ERR ERR + */ + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:+PrintInlining", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:+AlwaysSafeConstructors", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:+FlightRecorder", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:+PrintInlining", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:+AlwaysSafeConstructors", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:+FlightRecorder", "-version"); + + /* + #1.8 malformed locked flag: + diagnostic & locked experimental & locked commercial & locked + -XX:-UnlockDiagnosticVMOptions -XX:-UnlockExperimentalVMOptions -XX:-UnlockCommercialFeatures + -XX:PrintInlining -XX:AlwaysSafeConstructors -XX:FlightRecorder + -IgnoreUnrecognizedVMOptions ERR ERR ERR + +IgnoreUnrecognizedVMOptions ERR ERR ERR + */ + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:PrintInlining", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:AlwaysSafeConstructors", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:FlightRecorder", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:PrintInlining", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:AlwaysSafeConstructors", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:FlightRecorder", "-version"); + + /* + #1.9 malformed unlocked flag: + diagnostic & locked experimental & locked commercial & locked + -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockCommercialFeatures + -XX:PrintInlining -XX:AlwaysSafeConstructors -XX:FlightRecorder + -IgnoreUnrecognizedVMOptions ERR ERR ERR + +IgnoreUnrecognizedVMOptions ERR ERR ERR + */ + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:PrintInlining", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:AlwaysSafeConstructors", "-version"); + runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:FlightRecorder", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:PrintInlining", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:AlwaysSafeConstructors", "-version"); + runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:FlightRecorder", "-version"); + } +} diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java index 38b3239eb14..fa9ad87eb52 100644 --- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java @@ -29,7 +29,7 @@ * java.management * jdk.attach * jdk.management/sun.tools.attach - * @run main/othervm/timeout=600 TestOptionsWithRanges + * @run main/othervm/timeout=780 TestOptionsWithRanges */ import java.util.ArrayList; @@ -70,6 +70,8 @@ public class TestOptionsWithRanges { allOptionsAsMap.remove("G1ConcRefinementThreads"); allOptionsAsMap.remove("G1RSetRegionEntries"); allOptionsAsMap.remove("G1RSetSparseRegionEntries"); + allOptionsAsMap.remove("G1UpdateBufferSize"); + allOptionsAsMap.remove("InitialBootClassLoaderMetaspaceSize"); /* * Remove parameters controlling the code cache. As these diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java index d0f9e0b0819..7158b356eed 100644 --- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java @@ -115,20 +115,6 @@ public class JVMOptionsUtils { } - /** - * Add dependency for option depending on it's type. E.g. run the JVM in - * compilation mode for compiler options. - * - * @param option option - * @param type type of the option - */ - private static void addTypeDependency(JVMOption option, String type) { - if (type.contains("C1") || type.contains("C2")) { - /* Run in compiler mode for compiler flags */ - option.addPrepend("-Xcomp"); - } - } - /** * Parse JVM Options. Get input from "inputReader". Parse using * "-XX:+PrintFlagsRanges" output format. @@ -214,7 +200,6 @@ public class JVMOptionsUtils { token = token.substring(1, token.indexOf("}")); if (acceptOrigin.test(token)) { - addTypeDependency(option, token); addNameDependency(option); allOptions.put(name, option); diff --git a/hotspot/test/runtime/CompressedOops/UseCompressedOops.java b/hotspot/test/runtime/CompressedOops/UseCompressedOops.java index 2db3e0ac002..ac60e764e75 100644 --- a/hotspot/test/runtime/CompressedOops/UseCompressedOops.java +++ b/hotspot/test/runtime/CompressedOops/UseCompressedOops.java @@ -26,6 +26,7 @@ * @bug 8022865 * @summary Tests for different combination of UseCompressedOops options * @library /testlibrary + * @ignore 8079353 * @modules java.base/sun.misc * java.management * @run main UseCompressedOops diff --git a/hotspot/test/runtime/ErrorHandling/SecondaryErrorTest.java b/hotspot/test/runtime/ErrorHandling/SecondaryErrorTest.java index 37fac08130c..9c60d2d0c89 100644 --- a/hotspot/test/runtime/ErrorHandling/SecondaryErrorTest.java +++ b/hotspot/test/runtime/ErrorHandling/SecondaryErrorTest.java @@ -28,6 +28,7 @@ * @summary Synchronous signals during error reporting may terminate or hang VM process * @library /testlibrary * @author Thomas Stuefe (SAP) + * @requires os.family != "mac" * @modules java.base/sun.misc * java.management */ diff --git a/hotspot/test/runtime/NMT/ChangeTrackingLevel.java b/hotspot/test/runtime/NMT/ChangeTrackingLevel.java index a8fee254bf3..a5e8beb4a36 100644 --- a/hotspot/test/runtime/NMT/ChangeTrackingLevel.java +++ b/hotspot/test/runtime/NMT/ChangeTrackingLevel.java @@ -26,7 +26,7 @@ * @bug 8059100 * @summary Test that you can decrease NMT tracking level but not increase it. * @key nmt - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build ChangeTrackingLevel * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/NMT/JcmdDetailDiff.java b/hotspot/test/runtime/NMT/JcmdDetailDiff.java index 998e9aaa72e..4baeeb31e06 100644 --- a/hotspot/test/runtime/NMT/JcmdDetailDiff.java +++ b/hotspot/test/runtime/NMT/JcmdDetailDiff.java @@ -25,7 +25,7 @@ * @test * @summary run NMT baseline, allocate memory and verify output from detail.diff * @key nmt jcmd - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build JcmdDetailDiff diff --git a/hotspot/test/runtime/NMT/JcmdSummaryDiff.java b/hotspot/test/runtime/NMT/JcmdSummaryDiff.java index cd8612576fc..f74b523c838 100644 --- a/hotspot/test/runtime/NMT/JcmdSummaryDiff.java +++ b/hotspot/test/runtime/NMT/JcmdSummaryDiff.java @@ -25,7 +25,7 @@ * @test * @summary run NMT baseline, allocate memory and verify output from summary.diff * @key nmt jcmd - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build JcmdSummaryDiff diff --git a/hotspot/test/runtime/NMT/MallocRoundingReportTest.java b/hotspot/test/runtime/NMT/MallocRoundingReportTest.java index 0fd1717d025..2e9a9de68e8 100644 --- a/hotspot/test/runtime/NMT/MallocRoundingReportTest.java +++ b/hotspot/test/runtime/NMT/MallocRoundingReportTest.java @@ -25,7 +25,7 @@ * @test * @summary Test consistency of NMT by creating allocations of the Test type with various sizes and verifying visibility with jcmd * @key nmt jcmd - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build MallocRoundingReportTest diff --git a/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java b/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java index 0610764af95..7e754f4bbc2 100644 --- a/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java +++ b/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java @@ -26,7 +26,7 @@ * @summary Test corner case that overflows malloc site hashtable bucket * @requires sun.arch.data.model == "32" * @key nmt jcmd stress - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build MallocSiteHashOverflow * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocSiteHashOverflow diff --git a/hotspot/test/runtime/NMT/MallocStressTest.java b/hotspot/test/runtime/NMT/MallocStressTest.java index 548bf05c9a6..a798f71f9f4 100644 --- a/hotspot/test/runtime/NMT/MallocStressTest.java +++ b/hotspot/test/runtime/NMT/MallocStressTest.java @@ -25,7 +25,7 @@ * @test * @summary Stress test for malloc tracking * @key nmt jcmd stress - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build MallocStressTest diff --git a/hotspot/test/runtime/NMT/MallocTestType.java b/hotspot/test/runtime/NMT/MallocTestType.java index defbad448d5..4cc00ac1813 100644 --- a/hotspot/test/runtime/NMT/MallocTestType.java +++ b/hotspot/test/runtime/NMT/MallocTestType.java @@ -25,7 +25,7 @@ * @test * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd * @key nmt jcmd - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build MallocTestType diff --git a/hotspot/test/runtime/NMT/MallocTrackingVerify.java b/hotspot/test/runtime/NMT/MallocTrackingVerify.java index 06c9ec48107..8cbc497c1d6 100644 --- a/hotspot/test/runtime/NMT/MallocTrackingVerify.java +++ b/hotspot/test/runtime/NMT/MallocTrackingVerify.java @@ -26,7 +26,7 @@ * @bug 8054836 * @summary Test to verify correctness of malloc tracking * @key nmt jcmd - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build MallocTrackingVerify diff --git a/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java b/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java index 91790adcd64..8453d886ed8 100644 --- a/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java +++ b/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java @@ -26,7 +26,7 @@ * @bug 8013120 * @summary Release committed memory and make sure NMT handles it correctly * @key nmt regression - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build ReleaseCommittedMemory * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/NMT/ReleaseNoCommit.java b/hotspot/test/runtime/NMT/ReleaseNoCommit.java index 5009e8a2d61..a16d3ecdc66 100644 --- a/hotspot/test/runtime/NMT/ReleaseNoCommit.java +++ b/hotspot/test/runtime/NMT/ReleaseNoCommit.java @@ -25,7 +25,7 @@ * @test * @summary Release uncommitted memory and make sure NMT handles it correctly * @key nmt regression - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build ReleaseNoCommit diff --git a/hotspot/test/runtime/NMT/SummarySanityCheck.java b/hotspot/test/runtime/NMT/SummarySanityCheck.java index 25c154c2af0..b21ae9d7032 100644 --- a/hotspot/test/runtime/NMT/SummarySanityCheck.java +++ b/hotspot/test/runtime/NMT/SummarySanityCheck.java @@ -25,7 +25,7 @@ * @test * @key nmt jcmd * @summary Sanity check the output of NMT - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build SummarySanityCheck diff --git a/hotspot/test/runtime/NMT/ThreadedMallocTestType.java b/hotspot/test/runtime/NMT/ThreadedMallocTestType.java index 8906599dbcb..53d1b5513a9 100644 --- a/hotspot/test/runtime/NMT/ThreadedMallocTestType.java +++ b/hotspot/test/runtime/NMT/ThreadedMallocTestType.java @@ -24,7 +24,7 @@ /* * @test * @key nmt jcmd - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build ThreadedMallocTestType diff --git a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java index 36608158d05..c28df0a4eec 100644 --- a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java +++ b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java @@ -24,7 +24,7 @@ /* * @test * @key nmt jcmd - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build ThreadedVirtualAllocTestType diff --git a/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java b/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java index 379924bea45..4c71c11f396 100644 --- a/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java +++ b/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java @@ -25,7 +25,7 @@ * @test * @summary Test reserve/commit/uncommit/release of virtual memory and that we track it correctly * @key nmt jcmd - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build VirtualAllocCommitUncommitRecommit diff --git a/hotspot/test/runtime/NMT/VirtualAllocTestType.java b/hotspot/test/runtime/NMT/VirtualAllocTestType.java index 88bf42ca4ae..02a7923af66 100644 --- a/hotspot/test/runtime/NMT/VirtualAllocTestType.java +++ b/hotspot/test/runtime/NMT/VirtualAllocTestType.java @@ -25,7 +25,7 @@ * @test * @summary Test Reserve/Commit/Uncommit/Release of virtual memory and that we track it correctly * @key nmt jcmd - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build VirtualAllocTestType diff --git a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency1.java b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency1.java index e8f92a563cf..947f36ee8a6 100644 --- a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency1.java +++ b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency1.java @@ -25,7 +25,7 @@ * @test * @bug 8047290 * @summary Ensure that a Monitor::lock_without_safepoint_check fires an assert when it incorrectly acquires a lock which must always have safepoint checks. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build AssertSafepointCheckConsistency1 diff --git a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency2.java b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency2.java index 6a5a8b96076..6e24d0d17a1 100644 --- a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency2.java +++ b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency2.java @@ -25,7 +25,7 @@ * @test * @bug 8047290 * @summary Ensure that a Monitor::lock fires an assert when it incorrectly acquires a lock which must never have safepoint checks. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build AssertSafepointCheckConsistency2 diff --git a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency3.java b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency3.java index 6cd3ad09d59..c1395e0519a 100644 --- a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency3.java +++ b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency3.java @@ -25,7 +25,7 @@ * @test * @bug 8047290 * @summary Ensure that Monitor::lock_without_safepoint_check does not assert when it correctly acquires a lock which must never have safepoint checks. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build AssertSafepointCheckConsistency3 diff --git a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency4.java b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency4.java index 190b7798a7d..5d5449a28ac 100644 --- a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency4.java +++ b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency4.java @@ -25,7 +25,7 @@ * @test * @bug 8047290 * @summary Ensure that Monitor::lock does not assert when it correctly acquires a lock which must always have safepoint checks. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build AssertSafepointCheckConsistency4 diff --git a/hotspot/test/runtime/SameObject/SameObject.java b/hotspot/test/runtime/SameObject/SameObject.java new file mode 100644 index 00000000000..14ca5168ff2 --- /dev/null +++ b/hotspot/test/runtime/SameObject/SameObject.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, 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. + */ + +import jdk.test.lib.Asserts; + +/* + * @test + * @key cte_test + * @bug 4784641 + * @summary -Xcheck:jni overly strict in JNI method IsSameObject + * Fixed in JDK1.3.1_10 + * Fixed in JDK1.4.1_07 + * @library /testlibrary + * @run main/othervm/native -Xcheck:jni SameObject + */ +public class SameObject { + + public Object obj = new Object(); + + static { + System.loadLibrary("SameObject"); + } + + public native void createWeakRef(Object obj); + + public native int checkWeakRef(); + + public static void main(String[] args) throws Exception { + SameObject sameObject = new SameObject(); + + int result = sameObject.test(); + Asserts.assertEquals(result, 0, "WeakRef still alive"); + } + + public int test() { + createWeakRef(obj); + obj = null; + System.gc(); + try { + Thread.sleep(2000); + } catch (InterruptedException ex) { + System.out.println("Interrupted"); + } + + return checkWeakRef(); + } +} diff --git a/hotspot/test/runtime/SameObject/libSameObject.c b/hotspot/test/runtime/SameObject/libSameObject.c new file mode 100644 index 00000000000..5cc827732f7 --- /dev/null +++ b/hotspot/test/runtime/SameObject/libSameObject.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, 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 + +static jobject weakRef; + +/* + * Class: SameObject + * Method: createWeakRef + * Signature: (Ljava/lang/Object;)V + */ +JNIEXPORT void JNICALL Java_SameObject_createWeakRef +(JNIEnv *env, jobject obj1, jobject obj2) { + weakRef = (*env)->NewWeakGlobalRef(env, obj2); +} + +/* + * Class: SameObject + * Method: checkWeakRef + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_SameObject_checkWeakRef +(JNIEnv *env, jobject obj) { + return (*env)->IsSameObject(env, weakRef, NULL) ? 0 : 1; +} diff --git a/hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java new file mode 100644 index 00000000000..3f8669241c0 --- /dev/null +++ b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013, 2015, 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 CdsDifferentCompactStrings + * @summary CDS (class data sharing) requires the same -XX:[+-]CompactStrings + * setting between archive creation time and load time. + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + */ + +import jdk.test.lib.*; + +public class CdsDifferentCompactStrings { + public static void main(String[] args) throws Exception { + createAndLoadSharedArchive("+", "-"); + createAndLoadSharedArchive("-", "+"); + } + + private static void createAndLoadSharedArchive(String create, String load) + throws Exception + { + String createCompactStringsArgument = "-XX:" + create + "CompactStrings"; + String loadCompactStringsArgument = "-XX:" + load + "CompactStrings"; + + String filename = "./CdsDifferentCompactStrings" + create + ".jsa"; + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=" + filename, + "-Xshare:dump", + createCompactStringsArgument); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Loading classes to share"); + output.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=" + filename, + "-Xshare:on", + loadCompactStringsArgument, + "-version"); + + output = new OutputAnalyzer(pb.start()); + try { + output.shouldContain("The shared archive file's CompactStrings " + + "setting .* does not equal the current CompactStrings setting"); + } catch (RuntimeException e) { + output.shouldContain("Unable to use shared archive"); + } + output.shouldHaveExitValue(1); + } +} diff --git a/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java index 00179df6388..50906ea5d33 100644 --- a/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java +++ b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java @@ -29,7 +29,7 @@ * @requires (sun.arch.data.model != "32") & (os.family != "windows") * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) * @requires (vm.gc=="G1" | vm.gc=="null") - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build SharedStringsWb SharedStrings BasicJarBuilder sun.hotspot.WhiteBox diff --git a/hotspot/test/runtime/classFileParserBug/BadInitMethod.java b/hotspot/test/runtime/classFileParserBug/BadInitMethod.java index 3ac58a61f71..d0238bdf057 100644 --- a/hotspot/test/runtime/classFileParserBug/BadInitMethod.java +++ b/hotspot/test/runtime/classFileParserBug/BadInitMethod.java @@ -26,29 +26,59 @@ * @test * @bug 8130669 * @summary VM prohibits methods with return values - * @compile ignoredClinit.jasm + * @compile nonvoidClinit.jasm + * @compile clinitNonStatic.jasm + * @compile clinitArg.jasm + * @compile clinitArg51.jasm * @compile badInit.jasm * @run main/othervm -Xverify:all BadInitMethod */ -// Test that a non-void method does not cause an exception to be -// thrown. But that a non-void method causes a ClassFormatError -// exception. +// Test that non-void , non-static , and non-void +// methods cause ClassFormatException's to be thrown. public class BadInitMethod { public static void main(String args[]) throws Throwable { System.out.println("Regression test for bug 8130669"); try { - Class newClass = Class.forName("ignoredClinit"); - } catch (java.lang.Throwable e) { - throw new RuntimeException("Unexpected exception: " + e.getMessage()); + Class newClass = Class.forName("nonvoidClinit"); + throw new RuntimeException( + "Expected ClassFormatError exception for non-void not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test BadInitMethod passed for non-void "); + } + + try { + Class newClass = Class.forName("clinitNonStatic"); + throw new RuntimeException( + "Expected ClassFormatError exception for non-static not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test BadInitMethod passed for non-static "); + } + + // with args is allowed in class file version < 51. + try { + Class newClass = Class.forName("clinitArg"); + } catch (java.lang.ClassFormatError e) { + throw new RuntimeException( + "Unexpected ClassFormatError exception for with argument in class file < 51"); + } + + // with args is not allowed in class file version >= 51. + try { + Class newClass = Class.forName("clinitArg51"); + throw new RuntimeException( + "Expected ClassFormatError exception for with argument not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test BadInitMethod passed for with argument"); } try { Class newClass = Class.forName("badInit"); - throw new RuntimeException("Expected ClassFormatError exception not thrown"); + throw new RuntimeException( + "Expected ClassFormatError exception for non-void not thrown"); } catch (java.lang.ClassFormatError e) { - System.out.println("Test BadInitMethod passed"); + System.out.println("Test BadInitMethod passed for non-void "); } } } diff --git a/hotspot/test/runtime/classFileParserBug/clinitArg.jasm b/hotspot/test/runtime/classFileParserBug/clinitArg.jasm new file mode 100644 index 00000000000..57f68d0f575 --- /dev/null +++ b/hotspot/test/runtime/classFileParserBug/clinitArg.jasm @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +// This class contains a method with signature: (I)V. The JVM should +// not throw ClassFormatError because methods named that have arguments +// are not illegal in class file versions < 51. + +public class clinitArg version 50:0 +{ + + public static Method "":"(I)V" + stack 1 locals 1 + { + iconst_0; + return; + } + +} // end Class clinitArg diff --git a/hotspot/test/runtime/classFileParserBug/clinitArg51.jasm b/hotspot/test/runtime/classFileParserBug/clinitArg51.jasm new file mode 100644 index 00000000000..8b178bb282a --- /dev/null +++ b/hotspot/test/runtime/classFileParserBug/clinitArg51.jasm @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +// This class contains a method with signature: (I)V. The JVM should +// throw ClassFormatError because methods named that have arguments +// are illegal in class file version >= 51. + +public class clinitArg51 version 51:0 +{ + + public static Method "":"(I)V" + stack 1 locals 1 + { + iconst_0; + return; + } + +} // end Class clinitArg51 diff --git a/hotspot/test/runtime/classFileParserBug/clinitNonStatic.jasm b/hotspot/test/runtime/classFileParserBug/clinitNonStatic.jasm new file mode 100644 index 00000000000..2747a1eae00 --- /dev/null +++ b/hotspot/test/runtime/classFileParserBug/clinitNonStatic.jasm @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +// This class contains a non-static method. The JVM should +// throw ClassFormatError because methods named must be static +// in class file versions >= 51. + +public class clinitNonStatic version 51:0 +{ + + public Method "":"()V" + stack 1 locals 1 + { + iconst_0; + return; + } + +} // end Class clinitNonStatic diff --git a/hotspot/test/runtime/classFileParserBug/ignoredClinit.jasm b/hotspot/test/runtime/classFileParserBug/nonvoidClinit.jasm similarity index 86% rename from hotspot/test/runtime/classFileParserBug/ignoredClinit.jasm rename to hotspot/test/runtime/classFileParserBug/nonvoidClinit.jasm index 466b895b042..42112028e10 100644 --- a/hotspot/test/runtime/classFileParserBug/ignoredClinit.jasm +++ b/hotspot/test/runtime/classFileParserBug/nonvoidClinit.jasm @@ -23,10 +23,10 @@ */ // This class contains a method with signature: ()I. The JVM should -// not complain about this because methods named that have arguments -// and/or are not void should be ignored by the JVM. +// throw ClassFormatError because methods named that are not void +// are illegal. -public class ignoredClinit version 51:0 +public class nonvoidClinit version 51:0 { public static Method "":"()I" @@ -36,4 +36,4 @@ public class ignoredClinit version 51:0 ireturn; } -} // end Class ignoredClinit +} // end Class nonvoidClinit diff --git a/hotspot/test/runtime/interned/SanityTest.java b/hotspot/test/runtime/interned/SanityTest.java index 76ddb284521..6f07b0cc907 100644 --- a/hotspot/test/runtime/interned/SanityTest.java +++ b/hotspot/test/runtime/interned/SanityTest.java @@ -24,7 +24,7 @@ /* * @test SanityTest * @summary Sanity check of String.intern() & GC - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build SanityTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/logging/DefaultMethodsTest.java b/hotspot/test/runtime/logging/DefaultMethodsTest.java new file mode 100644 index 00000000000..50cbbe0e63d --- /dev/null +++ b/hotspot/test/runtime/logging/DefaultMethodsTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, 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 8139564 + * @summary defaultmethods=debug should have logging from each of the statements in the code + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @run main DefaultMethodsTest + */ + +import jdk.test.lib.*; + +public class DefaultMethodsTest { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:defaultmethods=debug", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Slots that need filling:"); + output.shouldContain("requires default method processing"); + output.shouldContain("Looking for default methods for slot "); + output.shouldContain("Creating defaults and overpasses..."); + output.shouldContain("for slot: "); + output.shouldContain("Default method processing complete"); + output.shouldContain("overpass methods"); + output.shouldContain("default methods"); + output.shouldHaveExitValue(0); + } +} + diff --git a/hotspot/test/runtime/logging/SafepointTest.java b/hotspot/test/runtime/logging/SafepointTest.java new file mode 100644 index 00000000000..fb6805e84bb --- /dev/null +++ b/hotspot/test/runtime/logging/SafepointTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, 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 8140348 + * @summary safepoint=trace should have output from each log statement in the code + * @library /testlibrary + * @compile SafepointTestMain.java + * @modules java.base/sun.misc + * java.management + * @build SafepointTest + * @run main SafepointTest + */ + +import jdk.test.lib.*; + +public class SafepointTest { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:safepoint=trace", "SafepointTestMain"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Safepoint synchronization initiated. ("); + output.shouldContain(" thread(s) to block"); + output.shouldContain("Entering safepoint region: "); + output.shouldContain("Leaving safepoint region"); + output.shouldContain("_at_poll_safepoint"); + output.shouldContain("... found polling page "); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/logging/SafepointTestMain.java b/hotspot/test/runtime/logging/SafepointTestMain.java new file mode 100644 index 00000000000..d69c0475dc0 --- /dev/null +++ b/hotspot/test/runtime/logging/SafepointTestMain.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015, 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. + */ + +import java.lang.ref.WeakReference; + +public class SafepointTestMain { + public static class B { + static int count = 0; + public static volatile boolean stop = false; + static void localSleep(int time) { + try{ + Thread.currentThread().sleep(time); + } catch(InterruptedException ie) { + } + } + + public static void infinite() { + while (!stop) { count++; } + } + } + + public static byte[] garbage; + public static volatile WeakReference weakref; + + public static void createweakref() { + Object o = new Object(); + weakref = new WeakReference<>(o); + } + + public static void main(String[] args) throws Exception { + // Run function in separate thread to force compilation and pint safepoint + // message for compiled method + new Thread() { + public void run() { + B.infinite(); + } + }.start(); + B.localSleep(1000); + // Cause several safepoints to run GC while the compiled method is running, + // to see safepoint messages + for (int i = 0; i < 2; i++) { + createweakref(); + while(weakref.get() != null) { + garbage = new byte[8192]; + System.gc(); + } + } + B.stop = true; + } +} diff --git a/hotspot/test/runtime/memory/ReadFromNoaccessArea.java b/hotspot/test/runtime/memory/ReadFromNoaccessArea.java index d8371058ecf..61227c5aa4a 100644 --- a/hotspot/test/runtime/memory/ReadFromNoaccessArea.java +++ b/hotspot/test/runtime/memory/ReadFromNoaccessArea.java @@ -24,7 +24,7 @@ /* * @test * @summary Test that touching noaccess area in class ReservedHeapSpace results in SIGSEGV/ACCESS_VIOLATION - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build ReadFromNoaccessArea diff --git a/hotspot/test/runtime/memory/ReadVMPageSize.java b/hotspot/test/runtime/memory/ReadVMPageSize.java index 09dfadaf75d..bbd23c5622c 100644 --- a/hotspot/test/runtime/memory/ReadVMPageSize.java +++ b/hotspot/test/runtime/memory/ReadVMPageSize.java @@ -24,7 +24,7 @@ /* * @test * @summary Using WhiteBox to get VM page size - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build ReadVMPageSize * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ReadVMPageSize diff --git a/hotspot/test/runtime/memory/ReserveMemory.java b/hotspot/test/runtime/memory/ReserveMemory.java index 4c0ecdcb8ce..bcc8fb1a7ef 100644 --- a/hotspot/test/runtime/memory/ReserveMemory.java +++ b/hotspot/test/runtime/memory/ReserveMemory.java @@ -26,7 +26,7 @@ * @key regression * @bug 8012015 * @summary Make sure reserved (but uncommitted) memory is not accessible - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build ReserveMemory diff --git a/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java b/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java index bc2181d66ad..27a05560988 100644 --- a/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java +++ b/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java @@ -24,7 +24,7 @@ /* * @test * @summary Test launches unit tests inside vm concurrently - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build RunUnitTestsConcurrently diff --git a/hotspot/test/runtime/memory/StressVirtualSpaceResize.java b/hotspot/test/runtime/memory/StressVirtualSpaceResize.java index 67ef73385ac..417c8de1463 100644 --- a/hotspot/test/runtime/memory/StressVirtualSpaceResize.java +++ b/hotspot/test/runtime/memory/StressVirtualSpaceResize.java @@ -24,7 +24,7 @@ /* * @test * @summary Stress test that expands/shrinks VirtualSpace - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build StressVirtualSpaceResize * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/whitebox/WBStackSize.java b/hotspot/test/runtime/whitebox/WBStackSize.java index 0941fb793df..0d3ccc36fc5 100644 --- a/hotspot/test/runtime/whitebox/WBStackSize.java +++ b/hotspot/test/runtime/whitebox/WBStackSize.java @@ -24,7 +24,7 @@ /* * @test WBStackSize * @summary verify that whitebox functions getThreadFullStackSize() and getThreadRemainingStackSize are working - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build WBStackSize * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/sanity/WBApi.java b/hotspot/test/sanity/WBApi.java index a1418e170fd..75ac5c3ab57 100644 --- a/hotspot/test/sanity/WBApi.java +++ b/hotspot/test/sanity/WBApi.java @@ -24,7 +24,7 @@ /* * @test WBApi * @summary verify that whitebox functions can be linked and executed - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build WBApi * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/serviceability/ParserTest.java b/hotspot/test/serviceability/ParserTest.java index 37a35de9a91..a9d6c8dbb7d 100644 --- a/hotspot/test/serviceability/ParserTest.java +++ b/hotspot/test/serviceability/ParserTest.java @@ -24,7 +24,7 @@ /* * @test * @summary Test that the diagnostic command arguemnt parser works - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @build ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.parser.* * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java index ac2a8717b32..bbf073a827c 100644 --- a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java +++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java @@ -25,7 +25,7 @@ * @test * @summary Test of diagnostic command GC.heap_dump -all=true * @library /testlibrary - * @library /../../test/lib/share/classes + * @library /test/lib/share/classes * @modules java.base/sun.misc * java.compiler * java.management diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java index 6ec4770fe80..20f766d3bf6 100644 --- a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java +++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java @@ -41,7 +41,7 @@ import jdk.test.lib.dcmd.PidJcmdExecutor; * @test * @summary Test of diagnostic command GC.heap_dump * @library /testlibrary - * @library /../../test/lib/share/classes + * @library /test/lib/share/classes * @modules java.base/sun.misc * java.compiler * java.management @@ -66,6 +66,7 @@ public class HeapDumpTest { String cmd = "GC.heap_dump " + heapDumpArgs + " " + dump.getAbsolutePath(); executor.execute(cmd); + verifyHeapDump(dump); dump.delete(); } diff --git a/hotspot/test/serviceability/sa/DeadlockDetectionTest.java b/hotspot/test/serviceability/sa/DeadlockDetectionTest.java index 637acbd9f27..aff1aaf156a 100644 --- a/hotspot/test/serviceability/sa/DeadlockDetectionTest.java +++ b/hotspot/test/serviceability/sa/DeadlockDetectionTest.java @@ -38,7 +38,7 @@ import jdk.test.lib.ProcessTools; /* * @test * @summary Test deadlock detection - * @library /../../test/lib/share/classes + * @library /test/lib/share/classes * @library /testlibrary * @modules java.management * @build jdk.test.lib.* diff --git a/hotspot/test/serviceability/sa/TestClassLoaderStats.java b/hotspot/test/serviceability/sa/TestClassLoaderStats.java index 944fc5b4492..92f843e11d9 100644 --- a/hotspot/test/serviceability/sa/TestClassLoaderStats.java +++ b/hotspot/test/serviceability/sa/TestClassLoaderStats.java @@ -32,7 +32,7 @@ import jdk.test.lib.apps.LingeredApp; /* * @test - * @library /../../test/lib/share/classes + * @library /test/lib/share/classes * @library /testlibrary * @build jdk.test.lib.* * @build jdk.test.lib.apps.* diff --git a/hotspot/test/serviceability/sa/TestStackTrace.java b/hotspot/test/serviceability/sa/TestStackTrace.java index e8f8ebbe15c..203735c3125 100644 --- a/hotspot/test/serviceability/sa/TestStackTrace.java +++ b/hotspot/test/serviceability/sa/TestStackTrace.java @@ -32,7 +32,7 @@ import jdk.test.lib.apps.LingeredApp; /* * @test - * @library /../../test/lib/share/classes + * @library /test/lib/share/classes * @library /testlibrary * @build jdk.test.lib.* * @build jdk.test.lib.apps.* diff --git a/hotspot/test/testlibrary/jdk/test/lib/Utils.java b/hotspot/test/testlibrary/jdk/test/lib/Utils.java index 535127cad7b..6776db006fe 100644 --- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java +++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java @@ -41,6 +41,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.Map; +import java.util.HashMap; import java.util.List; import java.util.Random; import java.util.function.BooleanSupplier; @@ -594,5 +596,25 @@ public final class Utils { } return result; } + + public static Object[] getNullValues(Class... types) { + Object[] result = new Object[types.length]; + int i = 0; + for (Class type : types) { + result[i++] = NULL_VALUES.get(type); + } + return result; + } + private static Map, Object> NULL_VALUES = new HashMap<>(); + static { + NULL_VALUES.put(boolean.class, false); + NULL_VALUES.put(byte.class, (byte) 0); + NULL_VALUES.put(short.class, (short) 0); + NULL_VALUES.put(char.class, '\0'); + NULL_VALUES.put(int.class, 0); + NULL_VALUES.put(long.class, 0L); + NULL_VALUES.put(float.class, 0.0f); + NULL_VALUES.put(double.class, 0.0d); + } } diff --git a/hotspot/test/testlibrary_tests/TestPlatformIsTieredSupported.java b/hotspot/test/testlibrary_tests/TestPlatformIsTieredSupported.java index b4931de671a..235aa3a5223 100644 --- a/hotspot/test/testlibrary_tests/TestPlatformIsTieredSupported.java +++ b/hotspot/test/testlibrary_tests/TestPlatformIsTieredSupported.java @@ -28,7 +28,7 @@ import sun.hotspot.WhiteBox; /** * @test * @summary Verifies that Platform::isTieredSupported returns correct value. - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management * @build TestPlatformIsTieredSupported diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java index dce204f88c6..8560fa6c5b3 100644 --- a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java +++ b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /../../test/lib /testlibrary/ctw/src + * @library /testlibrary /test/lib /testlibrary/ctw/src * @modules java.base/sun.misc * java.base/sun.reflect * java.management diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java index 7d33504001f..cb91c22bfe7 100644 --- a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java +++ b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /../../test/lib /testlibrary/ctw/src + * @library /testlibrary /test/lib /testlibrary/ctw/src * @modules java.base/sun.misc * java.base/sun.reflect * java.management diff --git a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java index cf56f434a93..c8ab89ca846 100644 --- a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java +++ b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /../../test/lib /testlibrary/ctw/src + * @library /testlibrary /test/lib /testlibrary/ctw/src * @modules java.base/sun.misc * java.base/sun.reflect * java.compiler diff --git a/hotspot/test/testlibrary_tests/ctw/JarsTest.java b/hotspot/test/testlibrary_tests/ctw/JarsTest.java index b6fb5ad93fd..f9ec895df38 100644 --- a/hotspot/test/testlibrary_tests/ctw/JarsTest.java +++ b/hotspot/test/testlibrary_tests/ctw/JarsTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /../../test/lib /testlibrary/ctw/src + * @library /testlibrary /test/lib /testlibrary/ctw/src * @modules java.base/sun.misc * java.base/sun.reflect * java.compiler diff --git a/hotspot/test/testlibrary_tests/whitebox/BlobSanityTest.java b/hotspot/test/testlibrary_tests/whitebox/BlobSanityTest.java index d8bf7970715..0ee48b5fb53 100644 --- a/hotspot/test/testlibrary_tests/whitebox/BlobSanityTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/BlobSanityTest.java @@ -24,7 +24,7 @@ /* * @test BlobSanityTest * @bug 8132980 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management/sun.management * @build BlobSanityTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java index 4c8c03c048b..7ba6f72088b 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java @@ -24,7 +24,7 @@ /* * @test BooleanTest * @bug 8028756 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.compiler * java.management/sun.management diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java index f3d42bd6c80..7a15c7dd9a1 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java @@ -24,7 +24,7 @@ /* * @test DoubleTest * @bug 8028756 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management/sun.management * @build DoubleTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java index 901d0dd3472..6b54127129c 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java @@ -24,7 +24,7 @@ /* * @test IntxTest * @bug 8028756 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management/sun.management * @build IntxTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java index 663e4ccc9ea..fcc18eb4251 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java @@ -24,7 +24,7 @@ /* * @test SizeTTest * @bug 8054823 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management/sun.management * @build SizeTTest diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java index e085c693905..531f59f4e32 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java @@ -24,7 +24,7 @@ /* * @test StringTest * @bug 8028756 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management/sun.management * @build StringTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java index c81667ecd64..c82e35ee54e 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java @@ -24,7 +24,7 @@ /* * @test Uint64Test * @bug 8028756 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.management/sun.management * @build Uint64Test * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java index 7c0699fa4ac..683a9c3339c 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java @@ -24,7 +24,7 @@ /* * @test UintxTest * @bug 8028756 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management/sun.management * @build UintxTest diff --git a/jaxp/.hgtags b/jaxp/.hgtags index a1e0320a6bf..ad660fbccf5 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -334,3 +334,5 @@ eb435c878c2cbbfb043d0b205f4d5bd6faffd44a jdk9-b87 5021da4c949690e5c2578c073c36fb161e4b35e5 jdk9-b89 35f68242b624112cb6ef7e6226059674d6b499f4 jdk9-b90 ffaff3d0ad0e0ca1e632b80826afa8729ee72a48 jdk9-b91 +fcabfb3c38ac1da99394e821902537d92e45222d jdk9-b92 +b9c50c63305cf1120263f6b7c6993021b53c2c40 jdk9-b93 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/XPath.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/XPath.java index be2e311c560..f6df2030c0c 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/XPath.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/XPath.java @@ -25,9 +25,12 @@ import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLSymbols; import com.sun.org.apache.xerces.internal.xni.NamespaceContext; import com.sun.org.apache.xerces.internal.xni.QName; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Vector; +import java.util.stream.Collectors; /** * Bare minimum XPath parser. @@ -47,20 +50,18 @@ public class XPath { private static final boolean DEBUG_XPATH_PARSE = DEBUG_ALL || false; - private static final boolean DEBUG_ANY = DEBUG_XPATH_PARSE; - // // Data // /** Expression. */ - protected String fExpression; + protected final String fExpression; /** Symbol table. */ - protected SymbolTable fSymbolTable; + protected final SymbolTable fSymbolTable; /** Location paths. */ - protected LocationPath[] fLocationPaths; + protected final LocationPath[] fLocationPaths; // // Constructors @@ -72,7 +73,7 @@ public class XPath { throws XPathException { fExpression = xpath; fSymbolTable = symbolTable; - parseExpression(context); + fLocationPaths = parseExpression(context); } // (String,SymbolTable,NamespaceContext) // @@ -101,15 +102,14 @@ public class XPath { // /** Returns a string representation of this object. */ + @Override public String toString() { - StringBuffer buf=new StringBuffer(); - for (int i=0;i0){ - buf.append("|"); - } - buf.append(fLocationPaths[i].toString()); - } - return buf.toString(); + final List l = Arrays.asList(fLocationPaths); + final String s = l.stream() + .map(aPath -> aPath.toString()) + .collect(Collectors.joining("|")); + + return s; } // toString():String // @@ -132,12 +132,12 @@ public class XPath { * to build a {@link LocationPath} object from the accumulated * {@link Step}s. */ - private LocationPath buildLocationPath( Vector stepsVector ) throws XPathException { + private LocationPath buildLocationPath( ArrayList stepsVector ) throws XPathException { int size = stepsVector.size(); check(size!=0); Step[] steps = new Step[size]; - stepsVector.copyInto(steps); - stepsVector.removeAllElements(); + steps = stepsVector.toArray(steps); + stepsVector.clear(); return new LocationPath(steps); } @@ -146,7 +146,7 @@ public class XPath { * This method is implemented by using the XPathExprScanner and * examining the list of tokens that it returns. */ - private void parseExpression(final NamespaceContext context) + private LocationPath[] parseExpression(final NamespaceContext context) throws XPathException { // tokens @@ -184,8 +184,8 @@ public class XPath { throw new XPathException("c-general-xpath"); //fTokens.dumpTokens(); - Vector stepsVector = new Vector(); - Vector locationPathsVector= new Vector(); + ArrayList stepsVector = new ArrayList<>(); + ArrayList locationPathsVector= new ArrayList<>(); // true when the next token should be 'Step' (as defined in // the production rule [3] of XML Schema P1 section 3.11.6 @@ -194,28 +194,39 @@ public class XPath { // this is to make sure we can detect a token list like // 'abc' '/' '/' 'def' 'ghi' boolean expectingStep = true; - boolean expectingDoubleColon = false; - while(xtokens.hasMore()) { + while (xtokens.hasMore()) { final int token = xtokens.nextToken(); switch (token) { case XPath.Tokens.EXPRTOKEN_OPERATOR_UNION :{ check(!expectingStep); - locationPathsVector.addElement(buildLocationPath(stepsVector)); + locationPathsVector.add(buildLocationPath(stepsVector)); expectingStep=true; break; } - case XPath.Tokens.EXPRTOKEN_ATSIGN: { check(expectingStep); Step step = new Step( new Axis(Axis.ATTRIBUTE), parseNodeTest(xtokens.nextToken(),xtokens,context)); - stepsVector.addElement(step); + stepsVector.add(step); expectingStep=false; break; } + case XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE: { + check(expectingStep); + // If we got here we're expecting attribute:: + if (xtokens.nextToken() != XPath.Tokens.EXPRTOKEN_DOUBLE_COLON) { + throw new XPathException("c-general-xpath"); + } + Step step = new Step( + new Axis(Axis.ATTRIBUTE), + parseNodeTest(xtokens.nextToken(),xtokens,context)); + stepsVector.add(step); + expectingStep = false; + break; + } case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY: case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE: case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME: { @@ -223,11 +234,23 @@ public class XPath { Step step = new Step( new Axis(Axis.CHILD), parseNodeTest(token,xtokens,context)); - stepsVector.addElement(step); + stepsVector.add(step); expectingStep=false; break; } - + case XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD: { + check(expectingStep); + // If we got here we're expecting child:: + if (xtokens.nextToken() != XPath.Tokens.EXPRTOKEN_DOUBLE_COLON) { + throw new XPathException("c-general-xpath"); + } + Step step = new Step( + new Axis(Axis.CHILD), + parseNodeTest(xtokens.nextToken(),xtokens,context)); + stepsVector.add(step); + expectingStep = false; + break; + } case XPath.Tokens.EXPRTOKEN_PERIOD: { check(expectingStep); expectingStep=false; @@ -237,12 +260,12 @@ public class XPath { // This amounts to shorten "a/././b/./c" to "a/b/c". // Also, the matcher fails to work correctly if XPath // has those redundant dots. - if (stepsVector.size()==0) { + if (stepsVector.isEmpty()) { // build step Axis axis = new Axis(Axis.SELF); NodeTest nodeTest = new NodeTest(NodeTest.NODE); Step step = new Step(axis, nodeTest); - stepsVector.addElement(step); + stepsVector.add(step); if( xtokens.hasMore() && xtokens.peekToken() == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH){ @@ -253,67 +276,41 @@ public class XPath { axis = new Axis(Axis.DESCENDANT); nodeTest = new NodeTest(NodeTest.NODE); step = new Step(axis, nodeTest); - stepsVector.addElement(step); + stepsVector.add(step); expectingStep=true; } } break; } - case XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH:{ - // this cannot appear in arbitrary position. + // this cannot appear in an arbitrary position. // it is only allowed right after '.' when // '.' is the first token of a location path. throw new XPathException("c-general-xpath"); } + case XPath.Tokens.EXPRTOKEN_DOUBLE_COLON: { + // :: cannot appear in an arbitrary position. + // We only expect this token if the xpath + // contains child:: or attribute:: + throw new XPathException("c-general-xpath"); + } case XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH: { check(!expectingStep); expectingStep=true; break; } - case XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE: { - check(expectingStep); - expectingDoubleColon = true; - - if (xtokens.nextToken() == XPath.Tokens.EXPRTOKEN_DOUBLE_COLON){ - Step step = new Step( - new Axis(Axis.ATTRIBUTE), - parseNodeTest(xtokens.nextToken(),xtokens,context)); - stepsVector.addElement(step); - expectingStep=false; - expectingDoubleColon = false; - } - break; - } - case XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD:{ - check(expectingStep); - expectingDoubleColon = true; - break; - } - case XPath.Tokens.EXPRTOKEN_DOUBLE_COLON :{ - check(expectingStep); - check(expectingDoubleColon); - expectingDoubleColon = false; - break; - } default: // we should have covered all the tokens that we can possibly see. - throw new XPathException("c-general-xpath"); - } + throw new InternalError(); + } } check(!expectingStep); - locationPathsVector.addElement(buildLocationPath(stepsVector)); + locationPathsVector.add(buildLocationPath(stepsVector)); - // save location path - fLocationPaths=new LocationPath[locationPathsVector.size()]; - locationPathsVector.copyInto(fLocationPaths); - - - if (DEBUG_XPATH_PARSE) { - System.out.println(">>> "+fLocationPaths); - } + // return location path + return locationPathsVector.toArray(new LocationPath[locationPathsVector.size()]); } // parseExpression(SymbolTable,NamespaceContext) @@ -378,7 +375,7 @@ public class XPath { // /** List of steps. */ - public Step[] steps; + public final Step[] steps; // // Constructors @@ -445,10 +442,10 @@ public class XPath { // /** Axis. */ - public Axis axis; + public final Axis axis; /** Node test. */ - public NodeTest nodeTest; + public final NodeTest nodeTest; // // Constructors @@ -525,7 +522,7 @@ public class XPath { // /** Axis type. */ - public short type; + public final short type; // // Constructors @@ -594,7 +591,7 @@ public class XPath { // /** Node test type. */ - public short type; + public final short type; /** Node qualified name. */ public final QName name = new QName(); @@ -856,13 +853,13 @@ public class XPath { private int[] fTokens = new int[INITIAL_TOKEN_COUNT]; private int fTokenCount = 0; // for writing - private SymbolTable fSymbolTable; + private final SymbolTable fSymbolTable; // REVISIT: Code something better here. -Ac - private Map fSymbolMapping = new HashMap<>(); + private final Map fSymbolMapping = new HashMap<>(); // REVISIT: Code something better here. -Ac - private Map fTokenNames = new HashMap<>(); + private final Map fTokenNames = new HashMap<>(); /** * Current position in the token list. @@ -1888,6 +1885,10 @@ public class XPath { tokens.addToken(nameHandle); } break; + default: + // CHARTYPE_INVALID or CHARTYPE_OTHER + // We're not expecting to find either of these in a valid expression. + return false; } } if (XPath.Tokens.DUMP_TOKENS) { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/XPathException.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/XPathException.java index 5e68d8bf021..719559d7a20 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/XPathException.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/XPathException.java @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2001, 2002,2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -37,7 +38,7 @@ public class XPathException // Data // hold the value of the key this Exception refers to. - private String fKey; + private final String fKey; // // Constructors // diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/BMPattern.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/BMPattern.java index 5fd796af1c7..49e7766cae2 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/BMPattern.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/BMPattern.java @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 1999-2002,2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -29,9 +30,9 @@ import java.text.CharacterIterator; * */ public class BMPattern { - char[] pattern; - int[] shiftTable; - boolean ignoreCase; + final char[] pattern; + final int[] shiftTable; + final boolean ignoreCase; public BMPattern(String pat, boolean ignoreCase) { this(pat, 256, ignoreCase); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/CaseInsensitiveMap.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/CaseInsensitiveMap.java index 3f5da982fa4..65f81d95c6c 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/CaseInsensitiveMap.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/CaseInsensitiveMap.java @@ -24,32 +24,27 @@ package com.sun.org.apache.xerces.internal.impl.xpath.regex; /** */ -public class CaseInsensitiveMap { +final class CaseInsensitiveMap { - private static int CHUNK_SHIFT = 10; /* 2^10 = 1k */ - private static int CHUNK_SIZE = (1< branches; UnionOp(int type, int size) { super(type); - this.branches = new Vector(size); + this.branches = new ArrayList<>(size); } void addElement(Op op) { - this.branches.addElement(op); + this.branches.add(op); } int size() { return this.branches.size(); } Op elementAt(int index) { - return (Op)this.branches.elementAt(index); + return this.branches.get(index); } } @@ -201,8 +202,8 @@ class Op { } // ================================================================ static class ModifierOp extends ChildOp { - int v1; - int v2; + final int v1; + final int v2; ModifierOp(int type, int v1, int v2) { super(type); this.v1 = v1; @@ -217,7 +218,7 @@ class Op { } // ================================================================ static class RangeOp extends Op { - Token tok; + final Token tok; RangeOp(int type, Token tok) { super(type); this.tok = tok; @@ -228,7 +229,7 @@ class Op { } // ================================================================ static class StringOp extends Op { - String string; + final String string; StringOp(int type, String literal) { super(type); this.string = literal; @@ -239,10 +240,10 @@ class Op { } // ================================================================ static class ConditionOp extends Op { - int refNumber; - Op condition; - Op yes; - Op no; + final int refNumber; + final Op condition; + final Op yes; + final Op no; ConditionOp(int type, int refno, Op conditionflow, Op yesflow, Op noflow) { super(type); this.refNumber = refno; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParseException.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParseException.java index ac4041e8b13..fba6de52143 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParseException.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParseException.java @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 1999-2002,2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -30,7 +31,7 @@ public class ParseException extends RuntimeException { /** Serialization version. */ static final long serialVersionUID = -7012400318097691370L; - int location; + final int location; /* public ParseException(String mes) { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParserForXMLSchema.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParserForXMLSchema.java index 3be13114a73..bc0ff0fea29 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParserForXMLSchema.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/ParserForXMLSchema.java @@ -252,7 +252,7 @@ class ParserForXMLSchema extends RegexParser { if (c == ']') throw this.ex("parser.cc.7", this.offset-2); if (c == '-' && this.chardata != ']' && !firstloop) throw this.ex("parser.cc.8", this.offset-2); // if regex = '[-]' then invalid } - if (this.read() != T_CHAR || this.chardata != '-' || c == '-' && firstloop) { // Here is no '-'. + if (this.read() != T_CHAR || this.chardata != '-' || c == '-' && !wasDecoded && firstloop) { // Here is no '-'. if (!this.isSet(RegularExpression.IGNORE_CASE) || c > 0xffff) { tok.addRange(c, c); } @@ -382,17 +382,20 @@ class ParserForXMLSchema extends RegexParser { ranges2.put("xml:isSpace", Token.complementRanges(tok)); tok = Token.createRange(); - setupRange(tok, DIGITS); - setupRange(tok, DIGITS_INT); + setupRange(tok, DIGITS_INTS); ranges.put("xml:isDigit", tok); ranges2.put("xml:isDigit", Token.complementRanges(tok)); + /* + * \w is defined by the XML Schema specification to be: + * [#x0000-#x10FFFF]-[\p{P}\p{Z}\p{C}] (all characters except the set of "punctuation", "separator" and "other" characters) + */ tok = Token.createRange(); - setupRange(tok, LETTERS); - setupRange(tok, LETTERS_INT); - tok.mergeRanges(ranges.get("xml:isDigit")); - ranges.put("xml:isWord", tok); - ranges2.put("xml:isWord", Token.complementRanges(tok)); + tok.mergeRanges(Token.getRange("P", true)); + tok.mergeRanges(Token.getRange("Z", true)); + tok.mergeRanges(Token.getRange("C", true)); + ranges2.put("xml:isWord", tok); + ranges.put("xml:isWord", Token.complementRanges(tok)); tok = Token.createRange(); setupRange(tok, NAMECHARS); @@ -401,6 +404,7 @@ class ParserForXMLSchema extends RegexParser { tok = Token.createRange(); setupRange(tok, LETTERS); + setupRange(tok, LETTERS_INT); tok.addRange('_', '_'); tok.addRange(':', ':'); ranges.put("xml:isInitialNameChar", tok); @@ -502,11 +506,12 @@ class ParserForXMLSchema extends RegexParser { private static final int[] LETTERS_INT = {0x1d790, 0x1d7a8, 0x1d7aa, 0x1d7c9, 0x2fa1b, 0x2fa1d}; - private static final String DIGITS = - "\u0030\u0039\u0660\u0669\u06F0\u06F9\u0966\u096F\u09E6\u09EF\u0A66\u0A6F\u0AE6\u0AEF" - +"\u0B66\u0B6F\u0BE7\u0BEF\u0C66\u0C6F\u0CE6\u0CEF\u0D66\u0D6F\u0E50\u0E59\u0ED0\u0ED9" - +"\u0F20\u0F29\u1040\u1049\u1369\u1371\u17E0\u17E9\u1810\u1819\uFF10\uFF19"; - - private static final int[] DIGITS_INT = {0x1D7CE, 0x1D7FF}; - + private static final int[] DIGITS_INTS = { + 0x0030, 0x0039, 0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F, + 0x09E6, 0x09EF, 0x0A66, 0x0A6F, 0x0AE6, 0x0AEF, 0x0B66, 0x0B6F, + 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 0x0D66, 0x0D6F, + 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F29, 0x1040, 0x1049, + 0x1369, 0x1371, 0x17E0, 0x17E9, 0x1810, 0x1819, 0xFF10, 0xFF19, + 0x1D7CE, 0x1D7FF + }; } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/REUtil.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/REUtil.java index 8f0a7d60794..dc96c08118f 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/REUtil.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/REUtil.java @@ -1,13 +1,13 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 1999-2002,2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -110,27 +110,27 @@ public final class REUtil { } static final String createOptionString(int options) { - StringBuffer sb = new StringBuffer(9); + StringBuilder sb = new StringBuilder(9); if ((options & RegularExpression.PROHIBIT_FIXED_STRING_OPTIMIZATION) != 0) - sb.append((char)'F'); + sb.append('F'); if ((options & RegularExpression.PROHIBIT_HEAD_CHARACTER_OPTIMIZATION) != 0) - sb.append((char)'H'); + sb.append('H'); if ((options & RegularExpression.XMLSCHEMA_MODE) != 0) - sb.append((char)'X'); + sb.append('X'); if ((options & RegularExpression.IGNORE_CASE) != 0) - sb.append((char)'i'); + sb.append('i'); if ((options & RegularExpression.MULTIPLE_LINES) != 0) - sb.append((char)'m'); + sb.append('m'); if ((options & RegularExpression.SINGLE_LINE) != 0) - sb.append((char)'s'); + sb.append('s'); if ((options & RegularExpression.USE_UNICODE_CATEGORY) != 0) - sb.append((char)'u'); + sb.append('u'); if ((options & RegularExpression.UNICODE_WORD_BOUNDARY) != 0) - sb.append((char)'w'); + sb.append('w'); if ((options & RegularExpression.EXTENDED_COMMENT) != 0) - sb.append((char)'x'); + sb.append('x'); if ((options & RegularExpression.SPECIAL_COMMA) != 0) - sb.append((char)','); + sb.append(','); return sb.toString().intern(); } @@ -138,13 +138,19 @@ public final class REUtil { static String stripExtendedComment(String regex) { int len = regex.length(); - StringBuffer buffer = new StringBuffer(len); + StringBuilder buffer = new StringBuilder(len); int offset = 0; + int charClass = 0; while (offset < len) { int ch = regex.charAt(offset++); // Skips a white space. - if (ch == '\t' || ch == '\n' || ch == '\f' || ch == '\r' || ch == ' ') + if (ch == '\t' || ch == '\n' || ch == '\f' || ch == '\r' || ch == ' ') { + // if we are inside a character class, we keep the white space + if (charClass > 0) { + buffer.append((char)ch); + } continue; + } if (ch == '#') { // Skips chracters between '#' and a line end. while (offset < len) { @@ -163,12 +169,36 @@ public final class REUtil { buffer.append((char)next); offset ++; } else { // Other escaped character. - buffer.append((char)'\\'); + buffer.append('\\'); buffer.append((char)next); offset ++; } - } else // As is. + } + else if (ch == '[') { + charClass++; buffer.append((char)ch); + if (offset < len) { + next = regex.charAt(offset); + if (next == '[' || next ==']') { + buffer.append((char)next); + offset ++; + } + else if (next == '^' && offset + 1 < len) { + next = regex.charAt(offset + 1); + if (next == '[' || next ==']') { + buffer.append('^'); + buffer.append((char)next); + offset += 2; + } + } + } + } + else { + if (charClass > 0 && ch == ']') { + --charClass; + } + buffer.append((char)ch); + } } return buffer.toString(); } @@ -307,15 +337,15 @@ public final class REUtil { */ public static String quoteMeta(String literal) { int len = literal.length(); - StringBuffer buffer = null; + StringBuilder buffer = null; for (int i = 0; i < len; i ++) { int ch = literal.charAt(i); if (".*+?{[()|\\^$".indexOf(ch) >= 0) { if (buffer == null) { - buffer = new StringBuffer(i+(len-i)*2); + buffer = new StringBuilder(i+(len-i)*2); if (i > 0) buffer.append(literal.substring(0, i)); } - buffer.append((char)'\\'); + buffer.append('\\'); buffer.append((char)ch); } else if (buffer != null) buffer.append((char)ch); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RangeToken.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RangeToken.java index 192be06a35c..cd57eab9d15 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RangeToken.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RangeToken.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -43,7 +42,7 @@ final class RangeToken extends Token implements java.io.Serializable { this.setSorted(false); } - // for RANGE or NRANGE + // for RANGE or NRANGE protected void addRange(int start, int end) { this.icaseCache = null; //System.err.println("Token#addRange(): "+start+" "+end); @@ -560,7 +559,7 @@ final class RangeToken extends Token implements java.io.Serializable { sb.append(escapeCharInCharClass(this.ranges[i])); } else { sb.append(escapeCharInCharClass(this.ranges[i])); - sb.append((char)'-'); + sb.append('-'); sb.append(escapeCharInCharClass(this.ranges[i+1])); } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegexParser.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegexParser.java index 5435fc799d9..96d16ee3bfc 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegexParser.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegexParser.java @@ -1,13 +1,13 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 1999-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -24,7 +24,7 @@ import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; -import java.util.Vector; +import java.util.ArrayList; /** * A Regular Expression Parser. @@ -82,8 +82,7 @@ class RegexParser { int parenOpened = 1; int parennumber = 1; boolean hasBackReferences; - Vector references = null; - int parenCount = 0; + ArrayList references = null; public RegexParser() { this.setLocale(Locale.getDefault()); @@ -115,7 +114,7 @@ class RegexParser { return (this.options & flag) == flag; } - synchronized Token parse(String regex, int options) throws ParseException { + Token parse(String regex, int options) throws ParseException { this.options = options; this.offset = 0; this.setContext(S_NORMAL); @@ -132,15 +131,16 @@ class RegexParser { Token ret = this.parseRegex(); if (this.offset != this.regexlen) throw ex("parser.parse.1", this.offset); - if (parenCount < 0) - throw ex("parser.factor.0", this.offset); + if (this.read() != T_EOF) { + throw ex("parser.parse.1", this.offset-1); + } if (this.references != null) { for (int i = 0; i < this.references.size(); i ++) { - ReferencePosition position = (ReferencePosition)this.references.elementAt(i); + ReferencePosition position = this.references.get(i); if (this.parennumber <= position.refNumber) throw ex("parser.parse.2", position.position); } - this.references.removeAllElements(); + this.references.clear(); } return ret; } @@ -160,6 +160,7 @@ class RegexParser { return this.nexttoken; } + @SuppressWarnings("fallthrough") final void next() { if (this.offset >= this.regexlen) { this.chardata = -1; @@ -239,7 +240,6 @@ class RegexParser { break; case '(': ret = T_LPAREN; - parenCount++; if (this.offset >= this.regexlen) break; if (this.regex.charAt(this.offset) != '?') @@ -328,11 +328,10 @@ class RegexParser { */ Token parseTerm() throws ParseException { int ch = this.read(); - Token tok = null; if (ch == T_OR || ch == T_RPAREN || ch == T_EOF) { - tok = Token.createEmpty(); + return Token.createEmpty(); } else { - tok = this.parseFactor(); + Token tok = this.parseFactor(); Token concat = null; while ((ch = this.read()) != T_OR && ch != T_RPAREN && ch != T_EOF) { if (concat == null) { @@ -343,11 +342,8 @@ class RegexParser { concat.addChild(this.parseFactor()); //tok = Token.createConcat(tok, this.parseFactor()); } + return tok; } - if (ch == T_RPAREN) { - parenCount--; - } - return tok; } // ---------------------------------------------------------------- @@ -482,7 +478,7 @@ class RegexParser { while (this.offset + 1 < this.regexlen) { ch = this.regex.charAt(this.offset + 1); - if ('1' <= ch && ch <= '9') { + if ('0' <= ch && ch <= '9') { refno = (refno * 10) + (ch - '0'); if (refno < this.parennumber) { finalRefno= refno; @@ -498,8 +494,8 @@ class RegexParser { } this.hasBackReferences = true; - if (this.references == null) this.references = new Vector(); - this.references.addElement(new ReferencePosition(finalRefno, this.offset)); + if (this.references == null) this.references = new ArrayList<>(); + this.references.add(new ReferencePosition(finalRefno, this.offset)); this.offset ++; if (this.regex.charAt(this.offset) != ')') throw ex("parser.factor.1", this.offset); this.offset ++; @@ -615,7 +611,7 @@ class RegexParser { while (this.offset < this.regexlen) { final int ch = this.regex.charAt(this.offset); - if ('1' <= ch && ch <= '9') { + if ('0' <= ch && ch <= '9') { refnum = (refnum * 10) + (ch - '0'); if (refnum < this.parennumber) { ++this.offset; @@ -633,8 +629,8 @@ class RegexParser { Token tok = Token.createBackReference(finalRefnum); this.hasBackReferences = true; - if (this.references == null) this.references = new Vector(); - this.references.addElement(new ReferencePosition(finalRefnum, this.offset-2)); + if (this.references == null) this.references = new ArrayList<>(); + this.references.add(new ReferencePosition(finalRefnum, this.offset-2)); this.next(); return tok; } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegularExpression.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegularExpression.java index 0a996b27c10..b45d497e19f 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegularExpression.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/RegularExpression.java @@ -1,13 +1,13 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 1999-2002,2004,2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -1041,9 +1041,10 @@ public class RegularExpression implements java.io.Serializable { /** * @return -1 when not match; offset of the end of matched string when match. */ + @SuppressWarnings("fallthrough") private int match(Context con, Op op, int offset, int dx, int opts) { final ExpressionTarget target = con.target; - final Stack opStack = new Stack(); + final Stack opStack = new Stack<>(); final IntStack dataStack = new IntStack(); final boolean isSetIgnoreCase = isSet(opts, IGNORE_CASE); int retValue = -1; @@ -1322,7 +1323,7 @@ public class RegularExpression implements java.io.Serializable { return retValue; } - op = (Op) opStack.pop(); + op = opStack.pop(); offset = dataStack.pop(); switch (op.type) { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/Token.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/Token.java index 3373a4c110d..49cc67203c1 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/Token.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/Token.java @@ -859,7 +859,7 @@ class Token implements java.io.Serializable { buffer.append("Is"); if (n.indexOf(' ') >= 0) { for (int ci = 0; ci < n.length(); ci ++) - if (n.charAt(ci) != ' ') buffer.append((char)n.charAt(ci)); + if (n.charAt(ci) != ' ') buffer.append(n.charAt(ci)); } else { buffer.append(n); @@ -995,8 +995,8 @@ class Token implements java.io.Serializable { } private static void setAlias(String newName, String name, boolean positive) { - Token t1 = (Token)Token.categories.get(name); - Token t2 = (Token)Token.categories2.get(name); + Token t1 = Token.categories.get(name); + Token t2 = Token.categories2.get(name); if (positive) { Token.categories.put(newName, t1); Token.categories2.put(newName, t2); @@ -1525,7 +1525,7 @@ class Token implements java.io.Serializable { this.children.stream().forEach((children1) -> { sb.append((children1).toString(options)); }); - ret = new String(sb); + ret = sb.toString(); } return ret; } @@ -1538,10 +1538,10 @@ class Token implements java.io.Serializable { StringBuilder sb = new StringBuilder(); sb.append((this.children.get(0)).toString(options)); for (int i = 1; i < this.children.size(); i ++) { - sb.append((char)'|'); + sb.append('|'); sb.append((this.children.get(i)).toString(options)); } - ret = new String(sb); + ret = sb.toString(); } return ret; } @@ -1557,7 +1557,7 @@ class Token implements java.io.Serializable { ObjectOutputStream.PutField pf = out.putFields(); pf.put("children", vChildren); out.writeFields(); - } + } @SuppressWarnings("unchecked") private void readObject(ObjectInputStream in) diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SafeThread.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SafeThread.java index abb5b3cffc1..4718d34cae6 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SafeThread.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SafeThread.java @@ -24,8 +24,6 @@ */ package com.sun.org.apache.xml.internal.utils; -import sun.misc.Unsafe; - /** * This is a combination of ThreadControllerWrapper's inner class SafeThread * that was introduced as a fix for CR 6607339 @@ -35,7 +33,7 @@ import sun.misc.Unsafe; */ public class SafeThread extends Thread { - private static final Unsafe UNSAFE; + private static final jdk.internal.misc.Unsafe UNSAFE; private static final long THREAD_LOCALS; private static final long INHERITABLE_THREAD_LOCALS; @@ -81,7 +79,7 @@ public class SafeThread extends Thread { } static { - UNSAFE = Unsafe.getUnsafe(); + UNSAFE = jdk.internal.misc.Unsafe.getUnsafe(); Class t = Thread.class; try { THREAD_LOCALS = UNSAFE.objectFieldOffset(t.getDeclaredField("threadLocals")); diff --git a/jaxp/test/TEST.ROOT b/jaxp/test/TEST.ROOT index a90bd60ac34..b78892aa12d 100644 --- a/jaxp/test/TEST.ROOT +++ b/jaxp/test/TEST.ROOT @@ -18,4 +18,4 @@ othervm.dirs=javax/xml/jaxp groups=TEST.groups # Minimum jtreg version -requiredVersion=4.1 b11 +requiredVersion=4.1 b12 diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/tck/RegexWord.java b/jaxp/test/javax/xml/jaxp/unittest/validation/tck/RegexWord.java new file mode 100644 index 00000000000..dd59b93a378 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/validation/tck/RegexWord.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, 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 validation.tck; + +import java.io.IOException; +import javax.xml.XMLConstants; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; +import org.testng.annotations.Test; +import org.xml.sax.SAXException; + +/* + * @bug 8142900 + * @summary Verifies that all characters except the set of "punctuation", + * "separator" and "other" characters are accepted by \w [#x0000-#x10FFFF]-[\p{P}\p{Z}\p{C}] + * @author Joe Wang + */ +public class RegexWord { + static final String SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; + static final String SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; + + /* + The original reZ003v.xml contains a full list of word characters that \w should accept. + However, U+2308..U+230B were changed from Sm to either Ps or Pe in Unicode 7.0. + They are therefore excluded from the test. + + The test throws an Exception (and fails) if it fails to recognize any of characters. + */ + @Test + public void test() throws SAXException, IOException { + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = schemaFactory.newSchema(new StreamSource(RegexWord.class.getResourceAsStream("reZ003.xsd"))); + Validator validator = schema.newValidator(); + + validator.validate(new StreamSource(RegexWord.class.getResourceAsStream("reZ003vExc23082309.xml"))); + } +} diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/tck/reZ003.xsd b/jaxp/test/javax/xml/jaxp/unittest/validation/tck/reZ003.xsd new file mode 100644 index 00000000000..c18a586613c --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/validation/tck/reZ003.xsd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/tck/reZ003vExc23082309.xml b/jaxp/test/javax/xml/jaxp/unittest/validation/tck/reZ003vExc23082309.xml new file mode 100644 index 00000000000..63253cffe42 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/validation/tck/reZ003vExc23082309.xml @@ -0,0 +1,9273 @@ + +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F +G +H +I +P +Q +R +S +T +U +V +W +X +Y +` +a +b +c +d +e +f +g +h +i +p +q +r +s +t +u +v +w +x +y +Ā +ā +Ă +ă +Ą +ą +Ć +ć +Ĉ +ĉ +Đ +đ +Ē +ē +Ĕ +ĕ +Ė +ė +Ę +ę +Ġ +ġ +Ģ +ģ +Ĥ +ĥ +Ħ +ħ +Ĩ +ĩ +İ +ı +IJ +ij +Ĵ +ĵ +Ķ +ķ +ĸ +Ĺ +ŀ +Ł +ł +Ń +ń +Ņ +ņ +Ň +ň +ʼn +Ő +ő +Œ +œ +Ŕ +ŕ +Ŗ +ŗ +Ř +ř +Š +š +Ţ +ţ +Ť +ť +Ŧ +ŧ +Ũ +ũ +Ű +ű +Ų +ų +Ŵ +ŵ +Ŷ +ŷ +Ÿ +Ź +ƀ +Ɓ +Ƃ +ƃ +Ƅ +ƅ +Ɔ +Ƈ +ƈ +Ɖ +Ɛ +Ƒ +ƒ +Ɠ +Ɣ +ƕ +Ɩ +Ɨ +Ƙ +ƙ +Ȁ +ȁ +Ȃ +ȃ +Ȅ +ȅ +Ȇ +ȇ +Ȉ +ȉ +Ȑ +ȑ +Ȓ +ȓ +Ȕ +ȕ +Ȗ +ȗ +Ș +ș +Ƞ +Ȣ +ȣ +Ȥ +ȥ +Ȧ +ȧ +Ȩ +ȩ +Ȱ +ȱ +Ȳ +ȳ +ɐ +ɑ +ɒ +ɓ +ɔ +ɕ +ɖ +ɗ +ɘ +ə +ɠ +ɡ +ɢ +ɣ +ɤ +ɥ +ɦ +ɧ +ɨ +ɩ +ɰ +ɱ +ɲ +ɳ +ɴ +ɵ +ɶ +ɷ +ɸ +ɹ +ʀ +ʁ +ʂ +ʃ +ʄ +ʅ +ʆ +ʇ +ʈ +ʉ +ʐ +ʑ +ʒ +ʓ +ʔ +ʕ +ʖ +ʗ +ʘ +ʙ +̀ +́ +̂ +̃ +̄ +̅ +̆ +̇ +̈ +̉ +̐ +̑ +̒ +̓ +̔ +̕ +̖ +̗ +̘ +̙ +̠ +̡ +̢ +̣ +̤ +̥ +̦ +̧ +̨ +̩ +̰ +̱ +̲ +̳ +̴ +̵ +̶ +̷ +̸ +̹ +̀ +́ +͂ +̓ +̈́ +ͅ +͆ +͇ +͈ +͉ +͠ +͡ +͢ +ͣ +ͤ +ͥ +ͦ +ͧ +ͨ +ͩ +ʹ +͵ +΄ +΅ +Ά +Έ +Ή +ΐ +Α +Β +Γ +Δ +Ε +Ζ +Η +Θ +Ι +Ѐ +Ё +Ђ +Ѓ +Є +Ѕ +І +Ї +Ј +Љ +А +Б +В +Г +Д +Е +Ж +З +И +Й +Р +С +Т +У +Ф +Х +Ц +Ч +Ш +Щ +а +б +в +г +д +е +ж +з +и +й +р +с +т +у +ф +х +ц +ч +ш +щ +ѐ +ё +ђ +ѓ +є +ѕ +і +ї +ј +љ +Ѡ +ѡ +Ѣ +ѣ +Ѥ +ѥ +Ѧ +ѧ +Ѩ +ѩ +Ѱ +ѱ +Ѳ +ѳ +Ѵ +ѵ +Ѷ +ѷ +Ѹ +ѹ +Ҁ +ҁ +҂ +҃ +҄ +҅ +҆ +҈ +҉ +Ґ +ґ +Ғ +ғ +Ҕ +ҕ +Җ +җ +Ҙ +ҙ +Ԁ +ԁ +Ԃ +ԃ +Ԅ +ԅ +Ԇ +ԇ +Ԉ +ԉ +Ա +Բ +Գ +Դ +Ե +Զ +Է +Ը +Թ +Հ +Ձ +Ղ +Ճ +Մ +Յ +Ն +Շ +Ո +Չ +Ր +Ց +Ւ +Փ +Ք +Օ +Ֆ +ՙ +ա +բ +գ +դ +ե +զ +է +ը +թ +հ +ձ +ղ +ճ +մ +յ +ն +շ +ո +չ +ր +ց +ւ +փ +ք +օ +ֆ +և +֑ +֒ +֓ +֔ +֕ +֖ +֗ +֘ +֙ +ء +آ +أ +ؤ +إ +ئ +ا +ب +ة +ذ +ر +ز +س +ش +ص +ض +ط +ظ +ع +ـ +ف +ق +ك +ل +م +ن +ه +و +ى +ِ +ّ +ْ +ٓ +ٔ +ٕ +٠ +١ +٢ +٣ +٤ +٥ +٦ +٧ +٨ +٩ +ٰ +ٱ +ٲ +ٳ +ٴ +ٵ +ٶ +ٷ +ٸ +ٹ +ڀ +ځ +ڂ +ڃ +ڄ +څ +چ +ڇ +ڈ +ډ +ڐ +ڑ +ڒ +ړ +ڔ +ڕ +ږ +ڗ +ژ +ڙ +ܐ +ܑ +ܒ +ܓ +ܔ +ܕ +ܖ +ܗ +ܘ +ܙ +ܠ +ܡ +ܢ +ܣ +ܤ +ܥ +ܦ +ܧ +ܨ +ܩ +ܰ +ܱ +ܲ +ܳ +ܴ +ܵ +ܶ +ܷ +ܸ +ܹ +݀ +݁ +݂ +݃ +݄ +݅ +݆ +݇ +݈ +݉ +ހ +ށ +ނ +ރ +ބ +ޅ +ކ +އ +ވ +މ +ސ +ޑ +ޒ +ޓ +ޔ +ޕ +ޖ +ޗ +ޘ +ޙ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +က + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +䀀 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +倀 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +怀 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +瀀 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +耀 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +退 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 96337533829..240b4dc2ec3 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -337,3 +337,5 @@ f6425fec60abe3c096c5251be61e4621c817be80 jdk9-b88 2d84c6f4cbbac5871b099e97f8f968d9de6b52bc jdk9-b89 b3e45213d574618f6520fa6978e4a14ba577c2db jdk9-b90 3b2a3cb658e41618bd152a7598d12e1f0c10e8f7 jdk9-b91 +fe772cbc64f4e0418c5bf694e9e7123f02e1808f jdk9-b92 +5e94fbbb7032b3bba8254ddb1af8fc45a4d1448b jdk9-b93 diff --git a/jdk/.hgtags b/jdk/.hgtags index 4f2107c4212..be40dffb3f8 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -335,3 +335,5 @@ e8a66c0b05d786a282a7ff1d7eb4989afa30c891 jdk9-b86 b433e4dfb830fea60e5187e4580791b62cc362d2 jdk9-b90 97624df5026a2fb191793697dbd2c604c4d5c66e jdk9-b91 6a5c99506f44538b879d8635a3979849ed587130 jdk9-b92 +2f12392d0dde768150c83087cdbdd0d33a4d866c jdk9-b93 +559b626b01179420a94feb9c3d0f246970d2e3fa jdk9-b94 diff --git a/jdk/make/Import.gmk b/jdk/make/Import.gmk index 25560f02ff0..d4c5654aeac 100644 --- a/jdk/make/Import.gmk +++ b/jdk/make/Import.gmk @@ -34,11 +34,9 @@ include MakeBase.gmk ifneq ($(OPENJDK_TARGET_OS), windows) HOTSPOT_LIB_DIR := $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR) BASE_INSTALL_LIBRARIES_HERE := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR) - SA_INSTALL_LIBRARIES_HERE := $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.hotspot.agent$(OPENJDK_TARGET_CPU_LIBDIR) else HOTSPOT_LIB_DIR := $(HOTSPOT_DIST)/bin BASE_INSTALL_LIBRARIES_HERE := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base - SA_INSTALL_LIBRARIES_HERE := $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.hotspot.agent endif ################################################################################ @@ -58,10 +56,6 @@ HOTSPOT_BASE_IMPORT_FILES := \ Xusage.txt \ # -HOTSPOT_SA_IMPORT_FILES := \ - $(addprefix $(LIBRARY_PREFIX), saproc.* sawindbg.*) \ - # - $(eval $(call SetupCopyFiles,COPY_HOTSPOT_BASE, \ SRC := $(HOTSPOT_LIB_DIR), \ DEST := $(BASE_INSTALL_LIBRARIES_HERE), \ @@ -77,14 +71,6 @@ endif BASE_TARGETS := $(COPY_HOTSPOT_BASE) $(COPY_HOTSPOT_BASE_JVMLIB) -$(eval $(call SetupCopyFiles,COPY_HOTSPOT_SA, \ - SRC := $(HOTSPOT_LIB_DIR), \ - DEST := $(SA_INSTALL_LIBRARIES_HERE), \ - FILES := $(shell $(FIND) $(HOTSPOT_LIB_DIR) -type f \ - -a \( -name DUMMY $(addprefix -o$(SPACE)-name$(SPACE), $(HOTSPOT_SA_IMPORT_FILES)) \) ))) - -SA_TARGETS := $(COPY_HOTSPOT_SA) - ################################################################################ ifneq ($(STATIC_BUILD), true) @@ -213,34 +199,6 @@ endif ################################################################################ -$(JDK_OUTPUTDIR)/modules/jdk.hotspot.agent/_the.sa.jar.unpacked: $(HOTSPOT_DIST)/lib/sa-jdi.jar \ - $(SUPPORT_OUTPUTDIR)/gensrc/jdk.hotspot.agent/_the.sa.services - $(ECHO) $(LOG_INFO) Unzipping $( $@ +endef + +PROVIDER_FILE := META-INF/services/sun.jvmstat.monitor.MonitoredHostService + +# Merge the local and remote sevice providers into jdk.jvmstat/META-INF/services +$(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat/$(PROVIDER_FILE): \ + $(JDK_TOPDIR)/src/jdk.jvmstat/share/classes/$(PROVIDER_FILE) \ + $(JDK_TOPDIR)/src/jdk.jvmstat.rmi/share/classes/$(PROVIDER_FILE) + $(merge-providers) + +# Copy the same service file into jdk.jvmstat.rmi so that they are kept the same. +$(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat.rmi/$(PROVIDER_FILE): \ + $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat/$(PROVIDER_FILE) + $(install-file) + +################################################################################ + +jdk.jvmstat: $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat/$(PROVIDER_FILE) \ + $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat.rmi/$(PROVIDER_FILE) + +all: jdk.jvmstat + +.PHONY: all \ No newline at end of file diff --git a/jdk/make/gensrc/GensrcCommon.gmk b/jdk/make/gensrc/GensrcCommon.gmk index 09819e19d57..a3370639176 100644 --- a/jdk/make/gensrc/GensrcCommon.gmk +++ b/jdk/make/gensrc/GensrcCommon.gmk @@ -33,4 +33,3 @@ include TextFileProcessing.gmk include SetupJavaCompilers.gmk # We need the tools. include Tools.gmk - diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk index 7762a284952..1587cbcadc5 100644 --- a/jdk/make/gensrc/GensrcMisc.gmk +++ b/jdk/make/gensrc/GensrcMisc.gmk @@ -100,7 +100,6 @@ ifneq ($(OPENJDK_TARGET_OS), windows) SRC := $(GENSRC_UC_SRC), \ INCLUDE_FILES := $(GENSRC_UC_SRC_FILE), \ TOOLCHAIN := TOOLCHAIN_BUILD, \ - CFLAGS := $(filter -D%, $(CFLAGS_JDKEXE)), \ OBJECT_DIR := $(GENSRC_UC_BIN), \ OUTPUT_DIR := $(GENSRC_UC_BIN), \ PROGRAM := genUnixConstants)) diff --git a/jdk/make/gensrc/GensrcProperties.gmk b/jdk/make/gensrc/GensrcProperties.gmk index 7293a19bbeb..2cc6231175e 100644 --- a/jdk/make/gensrc/GensrcProperties.gmk +++ b/jdk/make/gensrc/GensrcProperties.gmk @@ -75,7 +75,7 @@ define SetupCompilePropertiesBody # Convert .../src//share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties # to .../support/gensrc//com/sun/tools/javac/resources/javac_zh_CN.java - # Strip away prefix and suffix, leaving for example only: + # Strip away prefix and suffix, leaving for example only: # "/share/classes/com/sun/tools/javac/resources/javac_zh_CN" $1_JAVAS := $$(patsubst $$($1_MODULE_PATH_ROOT)/%, \ $(SUPPORT_OUTPUTDIR)/gensrc/%, \ diff --git a/jdk/make/launcher/Launcher-jdk.jcmd.gmk b/jdk/make/launcher/Launcher-jdk.jcmd.gmk index 34d24418550..a742b1a2de3 100644 --- a/jdk/make/launcher/Launcher-jdk.jcmd.gmk +++ b/jdk/make/launcher/Launcher-jdk.jcmd.gmk @@ -30,7 +30,6 @@ $(eval $(call SetupBuildLauncher, jinfo, \ JAVA_ARGS := \ -Dsun.jvm.hotspot.debugger.useProcDebugger \ -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \ - APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \ MACOSX_SIGNED := true, \ )) @@ -39,7 +38,6 @@ $(eval $(call SetupBuildLauncher, jmap, \ JAVA_ARGS := \ -Dsun.jvm.hotspot.debugger.useProcDebugger \ -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \ - APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \ MACOSX_SIGNED := true, \ )) @@ -52,7 +50,6 @@ $(eval $(call SetupBuildLauncher, jstack, \ JAVA_ARGS := \ -Dsun.jvm.hotspot.debugger.useProcDebugger \ -Dsun.jvm.hotspot.debugger.useWindbgDebugger, \ - APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \ MACOSX_SIGNED := true, \ )) diff --git a/jdk/make/launcher/Launcher-jdk.jconsole.gmk b/jdk/make/launcher/Launcher-jdk.jconsole.gmk index 7c5ada82382..aa07823c54a 100644 --- a/jdk/make/launcher/Launcher-jdk.jconsole.gmk +++ b/jdk/make/launcher/Launcher-jdk.jconsole.gmk @@ -28,7 +28,6 @@ include LauncherCommon.gmk $(eval $(call SetupBuildLauncher, jconsole, \ MAIN_CLASS := sun.tools.jconsole.JConsole, \ JAVA_ARGS := -Djconsole.showOutputViewer, \ - APP_CLASSPATH := /lib/jconsole.jar /lib/tools.jar /classes, \ CFLAGS_windows := -DJAVAW, \ LIBS_windows := user32.lib, \ )) diff --git a/jdk/make/launcher/Launcher-jdk.jdi.gmk b/jdk/make/launcher/Launcher-jdk.jdi.gmk index acb2a7125ba..fcce98cf430 100644 --- a/jdk/make/launcher/Launcher-jdk.jdi.gmk +++ b/jdk/make/launcher/Launcher-jdk.jdi.gmk @@ -27,5 +27,4 @@ include LauncherCommon.gmk $(eval $(call SetupBuildLauncher, jdb, \ MAIN_CLASS := com.sun.tools.example.debug.tty.TTY, \ - APP_CLASSPATH := /lib/tools.jar /lib/sa-jdi.jar /classes, \ )) diff --git a/jdk/make/launcher/Launcher-jdk.jvmstat.gmk b/jdk/make/launcher/Launcher-jdk.jvmstat.rmi.gmk similarity index 100% rename from jdk/make/launcher/Launcher-jdk.jvmstat.gmk rename to jdk/make/launcher/Launcher-jdk.jvmstat.rmi.gmk diff --git a/jdk/make/launcher/LauncherCommon.gmk b/jdk/make/launcher/LauncherCommon.gmk index debc6337b60..b7d0ccf459e 100644 --- a/jdk/make/launcher/LauncherCommon.gmk +++ b/jdk/make/launcher/LauncherCommon.gmk @@ -64,7 +64,6 @@ JAVA_MANIFEST := $(JDK_TOPDIR)/src/java.base/windows/native/launcher/java.manife # Remaining parameters are named arguments. These include: # MAIN_CLASS The Java main class to launch # JAVA_ARGS Processed into a -DJAVA_ARGS C flag -# APP_CLASSPATH Processed into a -DAPP_CLASSPATH C flag # CFLAGS Additional CFLAGS # CFLAGS_windows Additional CFLAGS_windows # LIBS_unix Additional LIBS_unix @@ -103,15 +102,6 @@ define SetupBuildLauncherBody $1_CFLAGS += -DJAVA_ARGS=$$($1_JAVA_ARGS_STR) endif - ifneq ($$($1_APP_CLASSPATH), ) - $1_APP_CLASSPATH_STR := '{ $$(strip $$(foreach a, \ - $$($1_APP_CLASSPATH), "$$a"$(COMMA) )) }' - # Remove the trailing comma - $1_APP_CLASSPATH_STR := $$(strip $$(subst $$(COMMA) }', }', \ - $$($1_APP_CLASSPATH_STR))) - $1_CFLAGS += -DAPP_CLASSPATH=$$($1_APP_CLASSPATH_STR) - endif - $1_LIBS := ifeq ($(OPENJDK_TARGET_OS), macosx) ifeq ($$($1_MACOSX_SIGNED), true) diff --git a/jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk b/jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk index 9f2ff08d7be..c71634166b2 100644 --- a/jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk +++ b/jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk @@ -43,7 +43,7 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS := $(LIBDL), \ LIBS_solaris := -lc, \ - OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libj2ucrypto, \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libj2ucrypto, \ DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) $(BUILD_LIBJ2UCRYPTO): $(BUILD_LIBJAVA) diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index 7ae48fec8e3..c1c80820a71 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -138,9 +138,14 @@ SUNWprivate_1.1 { Java_java_lang_Double_longBitsToDouble; Java_java_lang_Double_doubleToRawLongBits; Java_java_lang_reflect_Proxy_defineClass0; - Java_java_lang_Shutdown_runAllFinalizers; Java_java_lang_Float_intBitsToFloat; Java_java_lang_Float_floatToRawIntBits; + Java_java_lang_StackFrameInfo_fillInStackFrames; + Java_java_lang_StackFrameInfo_setMethodInfo; + Java_java_lang_StackStreamFactory_checkStackWalkModes; + Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk; + Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames; + Java_java_lang_Shutdown_runAllFinalizers; Java_java_lang_StrictMath_IEEEremainder; Java_java_lang_StrictMath_acos; Java_java_lang_StrictMath_asin; diff --git a/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java b/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java index 46f8ce9af9d..0e3ca50bc26 100644 --- a/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java +++ b/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java @@ -89,7 +89,7 @@ public class MakeJavaSecurity { } // Filter out platform-unrelated ones. We only support - // #ifdef, #ifndef, and #endif. + // #ifdef, #ifndef, #else, and #endif. Nesting not supported (yet). int mode = 0; // 0: out of block, 1: in match, 2: in non-match Iterator iter = lines.iterator(); while (iter.hasNext()) { @@ -105,7 +105,17 @@ public class MakeJavaSecurity { } iter.remove(); } else if (line.startsWith("#ifndef ")) { - mode = line.endsWith(args[2])?2:1; + if (line.indexOf('-') > 0) { + mode = line.endsWith(args[2]+"-"+args[3]) ? 2 : 1; + } else { + mode = line.endsWith(args[2]) ? 2 : 1; + } + iter.remove(); + } else if (line.startsWith("#else")) { + if (mode == 0) { + throw new IllegalStateException("#else not in #if block"); + } + mode = 3 - mode; iter.remove(); } else { if (mode == 2) iter.remove(); @@ -150,7 +160,7 @@ public class MakeJavaSecurity { List args) throws IOException { // parse property until EOL, not including line breaks boolean first = true; - while (!line.isEmpty()) { + while (line != null && !line.isEmpty()) { if (!line.startsWith("#")) { if (!line.endsWith(",\\") || (!first && line.contains("="))) { @@ -169,6 +179,8 @@ public class MakeJavaSecurity { lines.add(String.format("%"+numSpaces+"s", "") + arg + ",\\"); } } - lines.add(line); + if (line != null) { + lines.add(line); + } } } diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index 02de8910651..296d393eea8 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -19,6 +19,7 @@ java.xml.crypto jdk.charsets jdk.deploy jdk.deploy.osx +jdk.vm.cds jdk.httpserver jdk.jfr jdk.management diff --git a/jdk/make/src/classes/build/tools/module/ext.modules b/jdk/make/src/classes/build/tools/module/ext.modules index 15c2e9d6ae0..d266d40847f 100644 --- a/jdk/make/src/classes/build/tools/module/ext.modules +++ b/jdk/make/src/classes/build/tools/module/ext.modules @@ -9,6 +9,7 @@ jdk.crypto.ec jdk.crypto.mscapi jdk.crypto.pkcs11 jdk.crypto.ucrypto +jdk.dynalink jdk.localedata jdk.naming.dns jdk.scripting.nashorn diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultSelectorProvider.java b/jdk/src/java.base/aix/classes/sun/nio/ch/DefaultSelectorProvider.java similarity index 61% rename from jdk/src/java.base/unix/classes/sun/nio/ch/DefaultSelectorProvider.java rename to jdk/src/java.base/aix/classes/sun/nio/ch/DefaultSelectorProvider.java index e812e535165..3f23cc4fa3b 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultSelectorProvider.java +++ b/jdk/src/java.base/aix/classes/sun/nio/ch/DefaultSelectorProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -26,8 +26,6 @@ package sun.nio.ch; import java.nio.channels.spi.SelectorProvider; -import java.security.AccessController; -import sun.security.action.GetPropertyAction; /** * Creates this platform's default SelectorProvider @@ -40,32 +38,10 @@ public class DefaultSelectorProvider { */ private DefaultSelectorProvider() { } - @SuppressWarnings("unchecked") - private static SelectorProvider createProvider(String cn) { - Class c; - try { - c = (Class)Class.forName(cn); - } catch (ClassNotFoundException x) { - throw new AssertionError(x); - } - try { - return c.newInstance(); - } catch (IllegalAccessException | InstantiationException x) { - throw new AssertionError(x); - } - - } - /** * Returns the default SelectorProvider. */ public static SelectorProvider create() { - String osname = AccessController - .doPrivileged(new GetPropertyAction("os.name")); - if (osname.equals("SunOS")) - return createProvider("sun.nio.ch.DevPollSelectorProvider"); - if (osname.equals("Linux")) - return createProvider("sun.nio.ch.EPollSelectorProvider"); return new sun.nio.ch.PollSelectorProvider(); } diff --git a/jdk/src/java.base/linux/classes/sun/nio/ch/DefaultSelectorProvider.java b/jdk/src/java.base/linux/classes/sun/nio/ch/DefaultSelectorProvider.java new file mode 100644 index 00000000000..1278f1583ee --- /dev/null +++ b/jdk/src/java.base/linux/classes/sun/nio/ch/DefaultSelectorProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, 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 sun.nio.ch; + +import java.nio.channels.spi.SelectorProvider; + +/** + * Creates this platform's default SelectorProvider + */ + +public class DefaultSelectorProvider { + + /** + * Prevent instantiation. + */ + private DefaultSelectorProvider() { } + + /** + * Returns the default SelectorProvider. + */ + public static SelectorProvider create() { + return new sun.nio.ch.EPollSelectorProvider(); + } + +} diff --git a/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java b/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java index 762706c1e88..5179cce2dbe 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,6 +54,8 @@ import sun.reflect.Reflection; import sun.reflect.ReflectionFactory; import sun.reflect.misc.ReflectUtil; +import static java.io.ObjectStreamField.*; + /** * Serialization's descriptor for classes. It contains the name and * serialVersionUID of the class. The ObjectStreamClass for a specific class @@ -1519,61 +1521,14 @@ public class ObjectStreamClass implements Serializable { * if class names equal, false otherwise. */ private static boolean classNamesEqual(String name1, String name2) { - name1 = name1.substring(name1.lastIndexOf('.') + 1); - name2 = name2.substring(name2.lastIndexOf('.') + 1); - return name1.equals(name2); + int idx1 = name1.lastIndexOf('.') + 1; + int idx2 = name2.lastIndexOf('.') + 1; + int len1 = name1.length() - idx1; + int len2 = name2.length() - idx2; + return len1 == len2 && + name1.regionMatches(idx1, name2, idx2, len1); } - /** - * Returns JVM type signature for given primitive. - */ - private static String getPrimitiveSignature(Class cl) { - if (cl == Integer.TYPE) - return "I"; - else if (cl == Byte.TYPE) - return "B"; - else if (cl == Long.TYPE) - return "J"; - else if (cl == Float.TYPE) - return "F"; - else if (cl == Double.TYPE) - return "D"; - else if (cl == Short.TYPE) - return "S"; - else if (cl == Character.TYPE) - return "C"; - else if (cl == Boolean.TYPE) - return "Z"; - else if (cl == Void.TYPE) - return "V"; - else - throw new InternalError(); - } - - /** - * Returns JVM type signature for given class. - */ - static String getClassSignature(Class cl) { - if (cl.isPrimitive()) - return getPrimitiveSignature(cl); - else - return appendClassSignature(new StringBuilder(), cl).toString(); - } - - private static StringBuilder appendClassSignature(StringBuilder sbuf, Class cl) { - while (cl.isArray()) { - sbuf.append('['); - cl = cl.getComponentType(); - } - - if (cl.isPrimitive()) - sbuf.append(getPrimitiveSignature(cl)); - else - sbuf.append('L').append(cl.getName().replace('.', '/')).append(';'); - - return sbuf; - } - /** * Returns JVM type signature for given list of parameters and return type. */ diff --git a/jdk/src/java.base/share/classes/java/io/ObjectStreamField.java b/jdk/src/java.base/share/classes/java/io/ObjectStreamField.java index f77c312da74..bf03a67d317 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectStreamField.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, 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 @@ -91,7 +91,7 @@ public class ObjectStreamField this.name = name; this.type = type; this.unshared = unshared; - signature = ObjectStreamClass.getClassSignature(type).intern(); + signature = getClassSignature(type).intern(); field = null; } @@ -123,6 +123,58 @@ public class ObjectStreamField } } + /** + * Returns JVM type signature for given primitive. + */ + private static String getPrimitiveSignature(Class cl) { + if (cl == Integer.TYPE) + return "I"; + else if (cl == Byte.TYPE) + return "B"; + else if (cl == Long.TYPE) + return "J"; + else if (cl == Float.TYPE) + return "F"; + else if (cl == Double.TYPE) + return "D"; + else if (cl == Short.TYPE) + return "S"; + else if (cl == Character.TYPE) + return "C"; + else if (cl == Boolean.TYPE) + return "Z"; + else if (cl == Void.TYPE) + return "V"; + else + throw new InternalError(); + } + + /** + * Returns JVM type signature for given class. + */ + static String getClassSignature(Class cl) { + if (cl.isPrimitive()) { + return getPrimitiveSignature(cl); + } else { + return appendClassSignature(new StringBuilder(), cl).toString(); + } + } + + static StringBuilder appendClassSignature(StringBuilder sbuf, Class cl) { + while (cl.isArray()) { + sbuf.append('['); + cl = cl.getComponentType(); + } + + if (cl.isPrimitive()) { + sbuf.append(getPrimitiveSignature(cl)); + } else { + sbuf.append('L').append(cl.getName().replace('.', '/')).append(';'); + } + + return sbuf; + } + /** * Creates an ObjectStreamField representing the given field with the * specified unshared setting. For compatibility with the behavior of @@ -137,7 +189,7 @@ public class ObjectStreamField name = field.getName(); Class ftype = field.getType(); type = (showType || ftype.isPrimitive()) ? ftype : Object.class; - signature = ObjectStreamClass.getClassSignature(ftype).intern(); + signature = getClassSignature(ftype).intern(); } /** diff --git a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index 3cd12eeac15..177bba66f61 100644 --- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -732,13 +732,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @return a reference to this object. */ public AbstractStringBuilder append(int i) { - if (i == Integer.MIN_VALUE) { - append("-2147483648"); - return this; - } - int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1 - : Integer.stringSize(i); - int spaceNeeded = count + appendedLength; + int spaceNeeded = count + Integer.stringSize(i); ensureCapacityInternal(spaceNeeded); if (isLatin1()) { Integer.getChars(i, spaceNeeded, value); @@ -764,13 +758,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @return a reference to this object. */ public AbstractStringBuilder append(long l) { - if (l == Long.MIN_VALUE) { - append("-9223372036854775808"); - return this; - } - int appendedLength = (l < 0) ? Long.stringSize(-l) + 1 - : Long.stringSize(l); - int spaceNeeded = count + appendedLength; + int spaceNeeded = count + Long.stringSize(l); ensureCapacityInternal(spaceNeeded); if (isLatin1()) { Long.getChars(l, spaceNeeded, value); diff --git a/jdk/src/java.base/share/classes/java/lang/Integer.java b/jdk/src/java.base/share/classes/java/lang/Integer.java index e956c3571ff..e34ae9d9395 100644 --- a/jdk/src/java.base/share/classes/java/lang/Integer.java +++ b/jdk/src/java.base/share/classes/java/lang/Integer.java @@ -396,7 +396,7 @@ public final class Integer extends Number implements Comparable { } while (charPos > offset); } - static final char [] DigitTens = { + static final byte[] DigitTens = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', @@ -409,7 +409,7 @@ public final class Integer extends Number implements Comparable { '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', } ; - static final char [] DigitOnes = { + static final byte[] DigitOnes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', @@ -422,21 +422,6 @@ public final class Integer extends Number implements Comparable { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', } ; - // I use the "invariant division by multiplication" trick to - // accelerate Integer.toString. In particular we want to - // avoid division by 10. - // - // The "trick" has roughly the same performance characteristics - // as the "classic" Integer.toString code on a non-JIT VM. - // The trick avoids .rem and .div calls but has a longer code - // path and is thus dominated by dispatch overhead. In the - // JIT case the dispatch overhead doesn't exist and the - // "trick" is considerably faster than the classic code. - // - // RE: Division by Invariant Integers using Multiplication - // T Gralund, P Montgomery - // ACM PLDI 1994 - // /** * Returns a {@code String} object representing the @@ -450,9 +435,7 @@ public final class Integer extends Number implements Comparable { */ @HotSpotIntrinsicCandidate public static String toString(int i) { - if (i == Integer.MIN_VALUE) - return "-2147483648"; - int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); + int size = stringSize(i); if (COMPACT_STRINGS) { byte[] buf = new byte[size]; getChars(i, size, buf); @@ -489,84 +472,105 @@ public final class Integer extends Number implements Comparable { * digit at the specified index (exclusive), and working * backwards from there. * - * Will fail if i == Integer.MIN_VALUE + * @implNote This method converts positive inputs into negative + * values, to cover the Integer.MIN_VALUE case. Converting otherwise + * (negative to positive) will expose -Integer.MIN_VALUE that overflows + * integer. */ static void getChars(int i, int index, byte[] buf) { int q, r; int charPos = index; - char sign = 0; - if (i < 0) { - sign = '-'; + boolean negative = i < 0; + if (!negative) { i = -i; } // Generate two digits per iteration - while (i >= 65536) { + while (i <= -100) { q = i / 100; - // really: r = i - (q * 100); - r = i - ((q << 6) + (q << 5) + (q << 2)); + r = (q * 100) - i; i = q; - buf [--charPos] = (byte)DigitOnes[r]; - buf [--charPos] = (byte)DigitTens[r]; + buf[--charPos] = DigitOnes[r]; + buf[--charPos] = DigitTens[r]; } - // Fall thru to fast mode for smaller numbers - // assert(i <= 65536, i); - for (;;) { - q = (i * 52429) >>> (16+3); - r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... - buf [--charPos] = (byte)digits [r]; - i = q; - if (i == 0) break; + // We know there are at most two digits left at this point. + q = i / 10; + r = (q * 10) - i; + buf[--charPos] = (byte)('0' + r); + + // Whatever left is the remaining digit. + if (q < 0) { + buf[--charPos] = (byte)('0' - q); } - if (sign != 0) { - buf [--charPos] = (byte)sign; + + if (negative) { + buf[--charPos] = (byte)'-'; } } static void getCharsUTF16(int i, int index, byte[] buf) { int q, r; int charPos = index; - char sign = 0; - if (i < 0) { - sign = '-'; + boolean negative = (i < 0); + if (!negative) { i = -i; } - // Generate two digits per iteration - while (i >= 65536) { + // Get 2 digits/iteration using ints + while (i <= -100) { q = i / 100; - // really: r = i - (q * 100); - r = i - ((q << 6) + (q << 5) + (q << 2)); + r = (q * 100) - i; i = q; StringUTF16.putChar(buf, --charPos, DigitOnes[r]); StringUTF16.putChar(buf, --charPos, DigitTens[r]); } - // Fall thru to fast mode for smaller numbers - // assert(i <= 65536, i); - for (;;) { - q = (i * 52429) >>> (16+3); - r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... - StringUTF16.putChar(buf, --charPos, Integer.digits[r]); - i = q; - if (i == 0) break; + // We know there are at most two digits left at this point. + q = i / 10; + r = (q * 10) - i; + StringUTF16.putChar(buf, --charPos, '0' + r); + + // Whatever left is the remaining digit. + if (q < 0) { + StringUTF16.putChar(buf, --charPos, '0' - q); } - if (sign != 0) { - StringUTF16.putChar(buf, --charPos, sign); + + if (negative) { + StringUTF16.putChar(buf, --charPos, '-'); } } + // Left here for compatibility reasons, see JDK-8143900. static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE }; - // Requires positive x + /** + * Returns the string representation size for a given int value. + * + * @param x int value + * @return string size + * + * @implNote There are other ways to compute this: e.g. binary search, + * but values are biased heavily towards zero, and therefore linear search + * wins. The iteration results are also routinely inlined in the generated + * code after loop unrolling. + */ static int stringSize(int x) { - for (int i=0; ; i++) - if (x <= sizeTable[i]) - return i+1; + int d = 1; + if (x >= 0) { + d = 0; + x = -x; + } + int p = -10; + for (int i = 1; i < 10; i++) { + if (x > p) + return i + d; + p = 10 * p; + } + return 10 + d; } /** diff --git a/jdk/src/java.base/share/classes/java/lang/LiveStackFrame.java b/jdk/src/java.base/share/classes/java/lang/LiveStackFrame.java new file mode 100644 index 00000000000..1ef4a2aa041 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/LiveStackFrame.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2015, 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 java.lang; + +import java.lang.StackWalker.StackFrame; +import java.util.EnumSet; +import java.util.Set; + +import static java.lang.StackWalker.ExtendedOption.LOCALS_AND_OPERANDS; + +/** + * UNSUPPORTED This interface is intended to be package-private + * or move to an internal package.

+ * + * {@code LiveStackFrame} represents a frame storing data and partial results. + * Each frame has its own array of local variables (JVMS section 2.6.1), + * its own operand stack (JVMS section 2.6.2) for a method invocation. + * + * @jvms 2.6 Frames + */ +/* package-private */ +interface LiveStackFrame extends StackFrame { + /** + * Return the monitors held by this stack frame. This method returns + * an empty array if no monitor is held by this stack frame. + * + * @return the monitors held by this stack frames + */ + public Object[] getMonitors(); + + /** + * Gets the local variable array of this stack frame. + * + *

A single local variable can hold a value of type boolean, byte, char, + * short, int, float, reference or returnAddress. A pair of local variables + * can hold a value of type long or double. In other words, + * a value of type long or type double occupies two consecutive local + * variables. For a value of primitive type, the element in the + * local variable array is an {@link PrimitiveValue} object; + * otherwise, the element is an {@code Object}. + * + * @return the local variable array of this stack frame. + */ + public Object[] getLocals(); + + /** + * Gets the operand stack of this stack frame. + * + *

+ * The 0-th element of the returned array represents the top of the operand stack. + * This method returns an empty array if the operand stack is empty. + * + *

Each entry on the operand stack can hold a value of any Java Virtual + * Machine Type. + * For a value of primitive type, the element in the returned array is + * an {@link PrimitiveValue} object; otherwise, the element is the {@code Object} + * on the operand stack. + * + * @return the operand stack of this stack frame. + */ + public Object[] getStack(); + + /** + * UNSUPPORTED This interface is intended to be package-private + * or move to an internal package.

+ * + * Represents a local variable or an entry on the operand whose value is + * of primitive type. + */ + public abstract class PrimitiveValue { + /** + * Returns the base type of this primitive value, one of + * {@code B, D, C, F, I, J, S, Z}. + * + * @return Name of a base type + * @jvms table 4.3-A + */ + abstract char type(); + + /** + * Returns the boolean value if this primitive value is of type boolean. + * @return the boolean value if this primitive value is of type boolean. + * + * @throws UnsupportedOperationException if this primitive value is not + * of type boolean. + */ + public boolean booleanValue() { + throw new UnsupportedOperationException("this primitive of type " + type()); + } + + /** + * Returns the int value if this primitive value is of type int. + * @return the int value if this primitive value is of type int. + * + * @throws UnsupportedOperationException if this primitive value is not + * of type int. + */ + public int intValue() { + throw new UnsupportedOperationException("this primitive of type " + type()); + } + + /** + * Returns the long value if this primitive value is of type long. + * @return the long value if this primitive value is of type long. + * + * @throws UnsupportedOperationException if this primitive value is not + * of type long. + */ + public long longValue() { + throw new UnsupportedOperationException("this primitive of type " + type()); + } + + /** + * Returns the char value if this primitive value is of type char. + * @return the char value if this primitive value is of type char. + * + * @throws UnsupportedOperationException if this primitive value is not + * of type char. + */ + public char charValue() { + throw new UnsupportedOperationException("this primitive of type " + type()); + } + + /** + * Returns the byte value if this primitive value is of type byte. + * @return the byte value if this primitive value is of type byte. + * + * @throws UnsupportedOperationException if this primitive value is not + * of type byte. + */ + public byte byteValue() { + throw new UnsupportedOperationException("this primitive of type " + type()); + } + + /** + * Returns the short value if this primitive value is of type short. + * @return the short value if this primitive value is of type short. + * + * @throws UnsupportedOperationException if this primitive value is not + * of type short. + */ + public short shortValue() { + throw new UnsupportedOperationException("this primitive of type " + type()); + } + + /** + * Returns the float value if this primitive value is of type float. + * @return the float value if this primitive value is of type float. + * + * @throws UnsupportedOperationException if this primitive value is not + * of type float. + */ + public float floatValue() { + throw new UnsupportedOperationException("this primitive of type " + type()); + } + + /** + * Returns the double value if this primitive value is of type double. + * @return the double value if this primitive value is of type double. + * + * @throws UnsupportedOperationException if this primitive value is not + * of type double. + */ + public double doubleValue() { + throw new UnsupportedOperationException("this primitive of type " + type()); + } + } + + + /** + * Gets {@code StackWalker} that can get locals and operands. + * + * @throws SecurityException if the security manager is present and + * denies access to {@code RuntimePermission("liveStackFrames")} + */ + public static StackWalker getStackWalker() { + return getStackWalker(EnumSet.noneOf(StackWalker.Option.class)); + } + + /** + * Gets a {@code StackWalker} instance with the given options specifying + * the stack frame information it can access, and which will traverse at most + * the given {@code maxDepth} number of stack frames. If no option is + * specified, this {@code StackWalker} obtains the method name and + * the class name with all + * {@linkplain StackWalker.Option#SHOW_HIDDEN_FRAMES hidden frames} skipped. + * The returned {@code StackWalker} can get locals and operands. + * + * @param options stack walk {@link StackWalker.Option options} + * + * @throws SecurityException if the security manager is present and + * it denies access to {@code RuntimePermission("liveStackFrames")}; or + * or if the given {@code options} contains + * {@link StackWalker.Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE} + * and it denies access to {@code StackFramePermission("retainClassReference")}. + */ + public static StackWalker getStackWalker(Set options) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("liveStackFrames")); + } + return StackWalker.newInstance(options, LOCALS_AND_OPERANDS); + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/LiveStackFrameInfo.java b/jdk/src/java.base/share/classes/java/lang/LiveStackFrameInfo.java new file mode 100644 index 00000000000..db8901ea731 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/LiveStackFrameInfo.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2015, 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 java.lang; + +import java.lang.StackWalker.Option; +import java.util.EnumSet; +import java.util.Set; + +import static java.lang.StackWalker.ExtendedOption.*; + +final class LiveStackFrameInfo extends StackFrameInfo implements LiveStackFrame { + private static Object[] EMPTY_ARRAY = new Object[0]; + + LiveStackFrameInfo(StackWalker walker) { + super(walker); + } + + // These fields are initialized by the VM if ExtendedOption.LOCALS_AND_OPERANDS is set + private Object[] monitors = EMPTY_ARRAY; + private Object[] locals = EMPTY_ARRAY; + private Object[] operands = EMPTY_ARRAY; + + @Override + public Object[] getMonitors() { + return monitors; + } + + @Override + public Object[] getLocals() { + return locals; + } + + @Override + public Object[] getStack() { + return operands; + } + + /* + * Convert primitive value to {@code Primitive} object to represent + * a local variable or an element on the operand stack of primitive type. + */ + static PrimitiveValue asPrimitive(boolean value) { + return new BooleanPrimitive(value); + } + + static PrimitiveValue asPrimitive(int value) { + return new IntPrimitive(value); + } + + static PrimitiveValue asPrimitive(short value) { + return new ShortPrimitive(value); + } + + static PrimitiveValue asPrimitive(char value) { + return new CharPrimitive(value); + } + + static PrimitiveValue asPrimitive(byte value) { + return new BytePrimitive(value); + } + + static PrimitiveValue asPrimitive(long value) { + return new LongPrimitive(value); + } + + static PrimitiveValue asPrimitive(float value) { + return new FloatPrimitive(value); + } + + static PrimitiveValue asPrimitive(double value) { + return new DoublePrimitive(value); + } + + private static class IntPrimitive extends PrimitiveValue { + final int value; + IntPrimitive(int value) { + this.value = value; + } + + @Override + public char type() { + return 'I'; + } + + @Override + public int intValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + private static class ShortPrimitive extends PrimitiveValue { + final short value; + ShortPrimitive(short value) { + this.value = value; + } + + @Override + public char type() { + return 'S'; + } + + @Override + public short shortValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + private static class BooleanPrimitive extends PrimitiveValue { + final boolean value; + BooleanPrimitive(boolean value) { + this.value = value; + } + + @Override + public char type() { + return 'Z'; + } + + @Override + public boolean booleanValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + private static class CharPrimitive extends PrimitiveValue { + final char value; + CharPrimitive(char value) { + this.value = value; + } + + @Override + public char type() { + return 'C'; + } + + @Override + public char charValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + private static class BytePrimitive extends PrimitiveValue { + final byte value; + BytePrimitive(byte value) { + this.value = value; + } + + @Override + public char type() { + return 'B'; + } + + @Override + public byte byteValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + private static class LongPrimitive extends PrimitiveValue { + final long value; + LongPrimitive(long value) { + this.value = value; + } + + @Override + public char type() { + return 'J'; + } + + @Override + public long longValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + private static class FloatPrimitive extends PrimitiveValue { + final float value; + FloatPrimitive(float value) { + this.value = value; + } + + @Override + public char type() { + return 'F'; + } + + @Override + public float floatValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + private static class DoublePrimitive extends PrimitiveValue { + final double value; + DoublePrimitive(double value) { + this.value = value; + } + + @Override + public char type() { + return 'D'; + } + + @Override + public double doubleValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/Long.java b/jdk/src/java.base/share/classes/java/lang/Long.java index b68e2c29b7d..d7d232f23b0 100644 --- a/jdk/src/java.base/share/classes/java/lang/Long.java +++ b/jdk/src/java.base/share/classes/java/lang/Long.java @@ -448,9 +448,7 @@ public final class Long extends Number implements Comparable { * @return a string representation of the argument in base 10. */ public static String toString(long i) { - if (i == Long.MIN_VALUE) - return "-9223372036854775808"; - int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); + int size = stringSize(i); if (COMPACT_STRINGS) { byte[] buf = new byte[size]; getChars(i, size, buf); @@ -481,58 +479,59 @@ public final class Long extends Number implements Comparable { } /** - * Places characters representing the integer i into the + * Places characters representing the long i into the * character array buf. The characters are placed into * the buffer backwards starting with the least significant * digit at the specified index (exclusive), and working * backwards from there. * - * Will fail if i == Long.MIN_VALUE + * @implNote This method converts positive inputs into negative + * values, to cover the Long.MIN_VALUE case. Converting otherwise + * (negative to positive) will expose -Long.MIN_VALUE that overflows + * long. */ static void getChars(long i, int index, byte[] buf) { long q; int r; int charPos = index; - char sign = 0; - if (i < 0) { - sign = '-'; + boolean negative = (i < 0); + if (!negative) { i = -i; } // Get 2 digits/iteration using longs until quotient fits into an int - while (i > Integer.MAX_VALUE) { + while (i <= Integer.MIN_VALUE) { q = i / 100; - // really: r = i - (q * 100); - r = (int)(i - ((q << 6) + (q << 5) + (q << 2))); + r = (int)((q * 100) - i); i = q; - buf[--charPos] = (byte)Integer.DigitOnes[r]; - buf[--charPos] = (byte)Integer.DigitTens[r]; + buf[--charPos] = Integer.DigitOnes[r]; + buf[--charPos] = Integer.DigitTens[r]; } // Get 2 digits/iteration using ints int q2; int i2 = (int)i; - while (i2 >= 65536) { + while (i2 <= -100) { q2 = i2 / 100; - // really: r = i2 - (q * 100); - r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2)); + r = (q2 * 100) - i2; i2 = q2; - buf[--charPos] = (byte)Integer.DigitOnes[r]; - buf[--charPos] = (byte)Integer.DigitTens[r]; + buf[--charPos] = Integer.DigitOnes[r]; + buf[--charPos] = Integer.DigitTens[r]; } - // Fall thru to fast mode for smaller numbers - // assert(i2 <= 65536, i2); - for (;;) { - q2 = (i2 * 52429) >>> (16+3); - r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ... - buf[--charPos] = (byte)Integer.digits[r]; - i2 = q2; - if (i2 == 0) break; + // We know there are at most two digits left at this point. + q2 = i2 / 10; + r = (q2 * 10) - i2; + buf[--charPos] = (byte)('0' + r); + + // Whatever left is the remaining digit. + if (q2 < 0) { + buf[--charPos] = (byte)('0' - q2); } - if (sign != 0) { - buf[--charPos] = (byte)sign; + + if (negative) { + buf[--charPos] = (byte)'-'; } } @@ -540,18 +539,16 @@ public final class Long extends Number implements Comparable { long q; int r; int charPos = index; - char sign = 0; - if (i < 0) { - sign = '-'; + boolean negative = (i < 0); + if (!negative) { i = -i; } // Get 2 digits/iteration using longs until quotient fits into an int - while (i > Integer.MAX_VALUE) { + while (i <= Integer.MIN_VALUE) { q = i / 100; - // really: r = i - (q * 100); - r = (int)(i - ((q << 6) + (q << 5) + (q << 2))); + r = (int)((q * 100) - i); i = q; StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]); StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]); @@ -560,38 +557,53 @@ public final class Long extends Number implements Comparable { // Get 2 digits/iteration using ints int q2; int i2 = (int)i; - while (i2 >= 65536) { + while (i2 <= -100) { q2 = i2 / 100; - // really: r = i2 - (q * 100); - r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2)); + r = (q2 * 100) - i2; i2 = q2; StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]); StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]); } - // Fall thru to fast mode for smaller numbers - // assert(i2 <= 65536, i2); - for (;;) { - q2 = (i2 * 52429) >>> (16+3); - r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ... - StringUTF16.putChar(buf, --charPos, Integer.digits[r]); - i2 = q2; - if (i2 == 0) break; + // We know there are at most two digits left at this point. + q2 = i2 / 10; + r = (q2 * 10) - i2; + StringUTF16.putChar(buf, --charPos, '0' + r); + + // Whatever left is the remaining digit. + if (q2 < 0) { + StringUTF16.putChar(buf, --charPos, '0' - q2); } - if (sign != 0) { - StringUTF16.putChar(buf, --charPos, sign); + + if (negative) { + StringUTF16.putChar(buf, --charPos, '-'); } } - // Requires positive x + /** + * Returns the string representation size for a given long value. + * + * @param x long value + * @return string size + * + * @implNote There are other ways to compute this: e.g. binary search, + * but values are biased heavily towards zero, and therefore linear search + * wins. The iteration results are also routinely inlined in the generated + * code after loop unrolling. + */ static int stringSize(long x) { - long p = 10; - for (int i=1; i<19; i++) { - if (x < p) - return i; - p = 10*p; + int d = 1; + if (x >= 0) { + d = 0; + x = -x; } - return 19; + long p = -10; + for (int i = 1; i < 19; i++) { + if (x > p) + return i + d; + p = 10 * p; + } + return 19 + d; } /** diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java index 92b175b0957..0019b5724cf 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java @@ -359,7 +359,14 @@ final class ProcessHandleImpl implements ProcessHandle { @Override public Stream children() { - return children(pid); + // The native OS code selects based on matching the requested parent pid. + // If the original parent exits, the pid may have been re-used for + // this newer process. + // Processes started by the original parent (now dead) will all have + // start times less than the start of this newer parent. + // Processes started by this newer parent will have start times equal + // or after this parent. + return children(pid).filter(ph -> startTime <= ((ProcessHandleImpl)ph).startTime); } /** @@ -408,11 +415,21 @@ final class ProcessHandleImpl implements ProcessHandle { int next = 0; // index of next process to check int count = -1; // count of subprocesses scanned long ppid = pid; // start looking for this parent + long ppStart = 0; + // Find the start time of the parent + for (int i = 0; i < size; i++) { + if (pids[i] == ppid) { + ppStart = starttimes[i]; + break; + } + } do { - // Scan from next to size looking for ppid - // if found, exchange it to index next + // Scan from next to size looking for ppid with child start time + // the same or later than the parent. + // If found, exchange it with index next for (int i = next; i < size; i++) { - if (ppids[i] == ppid) { + if (ppids[i] == ppid && + ppStart <= starttimes[i]) { swap(pids, i, next); swap(ppids, i, next); swap(starttimes, i, next); @@ -420,6 +437,7 @@ final class ProcessHandleImpl implements ProcessHandle { } } ppid = pids[++count]; // pick up the next pid to scan for + ppStart = starttimes[count]; // and its start time } while (count < next); final long[] cpids = pids; diff --git a/jdk/src/java.base/share/classes/java/lang/Runtime.java b/jdk/src/java.base/share/classes/java/lang/Runtime.java index e75fcb439cf..668357e7067 100644 --- a/jdk/src/java.base/share/classes/java/lang/Runtime.java +++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java @@ -44,7 +44,7 @@ import sun.reflect.Reflection; */ public class Runtime { - private static Runtime currentRuntime = new Runtime(); + private static final Runtime currentRuntime = new Runtime(); /** * Returns the runtime object associated with the current Java application. diff --git a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java new file mode 100644 index 00000000000..5c7fbde5810 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015, 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 java.lang; + +import jdk.internal.misc.JavaLangInvokeAccess; +import jdk.internal.misc.SharedSecrets; + +import static java.lang.StackWalker.Option.*; +import java.lang.StackWalker.StackFrame; +import java.util.Optional; +import java.util.OptionalInt; + +class StackFrameInfo implements StackFrame { + private final static JavaLangInvokeAccess jlInvokeAccess = + SharedSecrets.getJavaLangInvokeAccess(); + + // -XX:+MemberNameInStackFrame will initialize MemberName and all other fields; + // otherwise, VM will set the hidden fields (injected by the VM). + // -XX:+MemberNameInStackFrame is temporary to enable performance measurement + // + // Footprint improvement: MemberName::clazz and MemberName::name + // can replace StackFrameInfo::declaringClass and StackFrameInfo::methodName + // Currently VM sets StackFrameInfo::methodName instead of expanding MemberName::name + + final StackWalker walker; + final Class declaringClass; + final Object memberName; + final int bci; + + // methodName, fileName, and lineNumber will be lazily set by the VM + // when first requested. + private String methodName; + private String fileName = null; // default for unavailable filename + private int lineNumber = -1; // default for unavailable lineNumber + + /* + * Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser + * to use + */ + StackFrameInfo(StackWalker walker) { + this.walker = walker; + this.declaringClass = null; + this.bci = -1; + this.memberName = jlInvokeAccess.newMemberName(); + } + + @Override + public String getClassName() { + return declaringClass.getName(); + } + + @Override + public Class getDeclaringClass() { + walker.ensureAccessEnabled(RETAIN_CLASS_REFERENCE); + return declaringClass; + } + + // Call the VM to set methodName, lineNumber, and fileName + private synchronized void ensureMethodInfoInitialized() { + if (methodName == null) { + setMethodInfo(); + } + } + + @Override + public String getMethodName() { + ensureMethodInfoInitialized(); + return methodName; + } + + @Override + public Optional getFileName() { + ensureMethodInfoInitialized(); + return fileName != null ? Optional.of(fileName) : Optional.empty(); + } + + @Override + public OptionalInt getLineNumber() { + ensureMethodInfoInitialized(); + return lineNumber > 0 ? OptionalInt.of(lineNumber) : OptionalInt.empty(); + } + + @Override + public boolean isNativeMethod() { + ensureMethodInfoInitialized(); + return lineNumber == -2; + } + + @Override + public String toString() { + ensureMethodInfoInitialized(); + // similar format as StackTraceElement::toString + if (isNativeMethod()) { + return getClassName() + "." + getMethodName() + "(Native Method)"; + } else { + // avoid allocating Optional objects + return getClassName() + "." + getMethodName() + + "(" + (fileName != null ? fileName : "Unknown Source") + + (lineNumber > 0 ? ":" + lineNumber : " bci:" + bci) + ")"; + } + } + + /** + * Lazily initialize method name, file name, line number + */ + private native void setMethodInfo(); + + /** + * Fill in source file name and line number of the given StackFrame array. + */ + static native void fillInStackFrames(int startIndex, + Object[] stackframes, + int fromIndex, int toIndex); +} diff --git a/jdk/src/java.base/share/classes/java/lang/StackFramePermission.java b/jdk/src/java.base/share/classes/java/lang/StackFramePermission.java new file mode 100644 index 00000000000..58dcba496be --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/StackFramePermission.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 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 java.lang; + +/** + * Permission to access {@link StackWalker.StackFrame}. + * + * @see java.lang.StackWalker.Option#RETAIN_CLASS_REFERENCE + * @see StackWalker.StackFrame#getDeclaringClass() + */ +public class StackFramePermission extends java.security.BasicPermission { + private static final long serialVersionUID = 2841894854386706014L; + + /** + * Creates a new {@code StackFramePermission} object. + * + * @param name Permission name. Must be "retainClassReference". + * + * @throws IllegalArgumentException if {@code name} is invalid. + * @throws NullPointerException if {@code name} is {@code null}. + */ + public StackFramePermission(String name) { + super(name); + if (!name.equals("retainClassReference")) { + throw new IllegalArgumentException("name: " + name); + } + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java new file mode 100644 index 00000000000..34c60a755d0 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java @@ -0,0 +1,1106 @@ +/* + * Copyright (c) 2015, 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 java.lang; + +import sun.misc.VM; + +import java.io.PrintStream; +import java.lang.StackWalker.Option; +import java.lang.StackWalker.StackFrame; + +import java.lang.annotation.Native; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import static java.lang.StackStreamFactory.WalkerState.*; + +/** + * StackStreamFactory class provides static factory methods + * to get different kinds of stack walker/traverser. + * + * AbstractStackWalker provides the basic stack walking support + * fetching stack frames from VM in batches. + * + * AbstractStackWalker subclass is specialized for a specific kind of stack traversal + * to avoid overhead of Stream/Lambda + * 1. Support traversing Stream + * 2. StackWalker::getCallerClass + * 3. Throwable::init and Throwable::getStackTrace + * 4. AccessControlContext getting ProtectionDomain + */ +final class StackStreamFactory { + private StackStreamFactory() {} + + // Stack walk implementation classes to be excluded during stack walking + // lazily add subclasses when they are loaded. + private final static Set> stackWalkImplClasses = init(); + + private static final int SMALL_BATCH = 8; + private static final int BATCH_SIZE = 32; + private static final int LARGE_BATCH_SIZE = 256; + private static final int MIN_BATCH_SIZE = SMALL_BATCH; + + // These flags must match the values maintained in the VM + @Native private static final int DEFAULT_MODE = 0x0; + @Native private static final int FILL_CLASS_REFS_ONLY = 0x2; + @Native private static final int FILTER_FILL_IN_STACKTRACE = 0x10; + @Native private static final int SHOW_HIDDEN_FRAMES = 0x20; // LambdaForms are hidden by the VM + @Native private static final int FILL_LIVE_STACK_FRAMES = 0x100; + + /* + * For Throwable to use StackWalker, set useNewThrowable to true. + * Performance work and extensive testing is needed to replace the + * VM built-in backtrace filled in Throwable with the StackWalker. + */ + final static boolean useNewThrowable = getProperty("stackwalk.newThrowable", false); + final static boolean isDebug = getProperty("stackwalk.debug", false); + + static StackFrameTraverser + makeStackTraverser(StackWalker walker, Function, ? extends T> function) + { + if (walker.hasLocalsOperandsOption()) + return new LiveStackInfoTraverser(walker, function); + else + return new StackFrameTraverser(walker, function); + } + + /** + * Gets a stack stream to find caller class. + */ + static CallerClassFinder makeCallerFinder(StackWalker walker) { + return new CallerClassFinder(walker); + } + + static boolean useStackTrace(Throwable t) { + if (t instanceof VirtualMachineError) + return false; + + return VM.isBooted() && StackStreamFactory.useNewThrowable; + } + + /* + * This should only be used by Throwable::. + */ + static StackTrace makeStackTrace(Throwable ex) { + return StackTrace.dump(ex); + } + + /* + * This creates StackTrace for Thread::dumpThread to use. + */ + static StackTrace makeStackTrace() { + return StackTrace.dump(); + } + + enum WalkerState { + NEW, // the stream is new and stack walking has not started + OPEN, // the stream is open when it is being traversed. + CLOSED; // the stream is closed when the stack walking is done + } + + static abstract class AbstractStackWalker { + protected final StackWalker walker; + protected final Thread thread; + protected final int maxDepth; + protected final long mode; + protected int depth; // traversed stack depth + protected FrameBuffer frameBuffer; // buffer for VM to fill in + protected long anchor; + + // buffers to fill in stack frame information + protected AbstractStackWalker(StackWalker walker, int mode) { + this(walker, mode, Integer.MAX_VALUE); + } + protected AbstractStackWalker(StackWalker walker, int mode, int maxDepth) { + this.thread = Thread.currentThread(); + this.mode = toStackWalkMode(walker, mode); + this.walker = walker; + this.maxDepth = maxDepth; + this.depth = 0; + } + + private int toStackWalkMode(StackWalker walker, int mode) { + int newMode = mode; + if (walker.hasOption(Option.SHOW_HIDDEN_FRAMES) && + !fillCallerClassOnly(newMode) /* don't show hidden frames for getCallerClass */) + newMode |= SHOW_HIDDEN_FRAMES; + if (walker.hasLocalsOperandsOption()) + newMode |= FILL_LIVE_STACK_FRAMES; + return newMode; + } + + private boolean fillCallerClassOnly(int mode) { + return (mode|FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY; + } + /** + * A callback method to consume the stack frames. This method is invoked + * once stack walking begins (i.e. it is only invoked when walkFrames is called). + * + * Each specialized AbstractStackWalker subclass implements the consumeFrames method + * to control the following: + * 1. fetch the subsequent batches of stack frames + * 2. reuse or expand the allocated buffers + * 3. create specialized StackFrame objects + * + * @return the number of consumed frames + */ + protected abstract T consumeFrames(); + + /** + * Initialize FrameBuffer. Subclass should implement this method to + * create its custom frame buffers. + */ + protected abstract void initFrameBuffer(); + + /** + * Returns the suggested next batch size. + * + * Subclass should override this method to change the batch size + * + * @param lastBatchFrameCount number of frames in the last batch; or zero + * @return suggested batch size + */ + protected abstract int batchSize(int lastBatchFrameCount); + + /* + * Returns the next batch size, always >= minimum batch size (32) + * + * Subclass may override this method if the minimum batch size is different. + */ + protected int getNextBatchSize() { + int lastBatchSize = depth == 0 ? 0 : frameBuffer.curBatchFrameCount(); + int nextBatchSize = batchSize(lastBatchSize); + if (isDebug) { + System.err.println("last batch size = " + lastBatchSize + + " next batch size = " + nextBatchSize); + } + return nextBatchSize >= MIN_BATCH_SIZE ? nextBatchSize : MIN_BATCH_SIZE; + } + + /* + * Checks if this stream is in the given state. Otherwise, throws IllegalStateException. + * + * VM also validates this stream if it's anchored for stack walking + * when stack frames are fetched for each batch. + */ + final void checkState(WalkerState state) { + if (thread != Thread.currentThread()) { + throw new IllegalStateException("Invalid thread walking this stack stream: " + + Thread.currentThread().getName() + " " + thread.getName()); + } + switch (state) { + case NEW: + if (anchor != 0) { + throw new IllegalStateException("This stack stream is being reused."); + } + break; + case OPEN: + if (anchor == 0 || anchor == -1L) { + throw new IllegalStateException("This stack stream is not valid for walking."); + } + break; + case CLOSED: + if (anchor != -1L) { + throw new IllegalStateException("This stack stream is not closed."); + } + } + } + + /* + * Close this stream. This stream becomes invalid to walk. + */ + private void close() { + this.anchor = -1L; + } + + /* + * Walks stack frames until {@link #consumeFrames} is done consuming + * the frames it is interested in. + */ + final T walk() { + checkState(NEW); + try { + // VM will need to stablize the stack before walking. It will invoke + // the AbstractStackWalker::doStackWalk method once it fetches the first batch. + // the callback will be invoked within the scope of the callStackWalk frame. + return beginStackWalk(); + } finally { + close(); // done traversal; close the stream + } + } + + private boolean skipReflectionFrames() { + return !walker.hasOption(Option.SHOW_REFLECT_FRAMES) && + !walker.hasOption(Option.SHOW_HIDDEN_FRAMES); + } + + /* + * Returns {@code Class} object at the current frame; + * or {@code null} if no more frame. If advanceToNextBatch is true, + * it will only fetch the next batch. + */ + final Class peekFrame() { + while (frameBuffer.isActive() && depth < maxDepth) { + if (frameBuffer.isEmpty()) { + // fetch another batch of stack frames + getNextBatch(); + } else { + Class c = frameBuffer.get(); + if (skipReflectionFrames() && isReflectionFrame(c)) { + if (isDebug) + System.err.println(" skip: frame " + frameBuffer.getIndex() + " " + c); + + frameBuffer.next(); + depth++; + continue; + } else { + return c; + } + } + } + return null; + } + + /* + * This method is only invoked by VM. + * + * It will invoke the consumeFrames method to start the stack walking + * with the first batch of stack frames. Each specialized AbstractStackWalker + * subclass implements the consumeFrames method to control the following: + * 1. fetch the subsequent batches of stack frames + * 2. reuse or expand the allocated buffers + * 3. create specialized StackFrame objects + */ + private Object doStackWalk(long anchor, int skipFrames, int batchSize, + int bufStartIndex, int bufEndIndex) { + checkState(NEW); + + frameBuffer.check(skipFrames); + + if (isDebug) { + System.err.format("doStackWalk: skip %d start %d end %d%n", + skipFrames, bufStartIndex, bufEndIndex); + } + + this.anchor = anchor; // set anchor for this bulk stack frame traversal + frameBuffer.setBatch(bufStartIndex, bufEndIndex); + + // traverse all frames and perform the action on the stack frames, if specified + return consumeFrames(); + } + + /* + * Get next batch of stack frames. + */ + private int getNextBatch() { + int nextBatchSize = Math.min(maxDepth - depth, getNextBatchSize()); + if (!frameBuffer.isActive() || nextBatchSize <= 0) { + if (isDebug) { + System.out.format(" more stack walk done%n"); + } + frameBuffer.freeze(); // stack walk done + return 0; + } + + return fetchStackFrames(nextBatchSize); + } + + /* + * This method traverses the next stack frame and returns the Class + * invoking that stack frame. + * + * This method can only be called during the walk method. This is intended + * to be used to walk the stack frames in one single invocation and + * this stack stream will be invalidated once walk is done. + * + * @see #tryNextFrame + */ + final Class nextFrame() { + if (!hasNext()) { + return null; + } + + Class c = frameBuffer.next(); + depth++; + return c; + } + + /* + * Returns true if there is next frame to be traversed. + * This skips hidden frames unless this StackWalker has + * {@link Option#SHOW_REFLECT_FRAMES} + */ + final boolean hasNext() { + return peekFrame() != null; + } + + /** + * Begin stack walking - pass the allocated arrays to the VM to fill in + * stack frame information. + * + * VM first anchors the frame of the current thread. A traversable stream + * on this thread's stack will be opened. The VM will fetch the first batch + * of stack frames and call AbstractStackWalker::doStackWalk to invoke the + * stack walking function on each stack frame. + * + * If all fetched stack frames are traversed, AbstractStackWalker::fetchStackFrames will + * fetch the next batch of stack frames to continue. + */ + private T beginStackWalk() { + // initialize buffers for VM to fill the stack frame info + initFrameBuffer(); + + return callStackWalk(mode, 0, + frameBuffer.curBatchFrameCount(), + frameBuffer.startIndex(), + frameBuffer.classes, + frameBuffer.stackFrames); + } + + /* + * Fetches stack frames. + * + * @params batchSize number of elements of the frame buffers for this batch + * @returns number of frames fetched in this batch + */ + private int fetchStackFrames(int batchSize) { + int startIndex = frameBuffer.startIndex(); + frameBuffer.resize(startIndex, batchSize); + + int endIndex = fetchStackFrames(mode, anchor, batchSize, + startIndex, + frameBuffer.classes, + frameBuffer.stackFrames); + if (isDebug) { + System.out.format(" more stack walk requesting %d got %d to %d frames%n", + batchSize, frameBuffer.startIndex(), endIndex); + } + int numFrames = endIndex - startIndex; + if (numFrames == 0) { + frameBuffer.freeze(); // done stack walking + } else { + frameBuffer.setBatch(startIndex, endIndex); + } + return numFrames; + } + + /** + * Begins stack walking. This method anchors this frame and invokes + * AbstractStackWalker::doStackWalk after fetching the firt batch of stack frames. + * + * @param mode mode of stack walking + * @param skipframes number of frames to be skipped before filling the frame buffer. + * @param batchSize the batch size, max. number of elements to be filled in the frame buffers. + * @param startIndex start index of the frame buffers to be filled. + * @param classes Classes buffer of the stack frames + * @param frames StackFrame buffer, or null + * @return Result of AbstractStackWalker::doStackWalk + */ + private native T callStackWalk(long mode, int skipframes, + int batchSize, int startIndex, + Class[] classes, + StackFrame[] frames); + + /** + * Fetch the next batch of stack frames. + * + * @param mode mode of stack walking + * @param anchor + * @param batchSize the batch size, max. number of elements to be filled in the frame buffers. + * @param startIndex start index of the frame buffers to be filled. + * @param classes Classes buffer of the stack frames + * @param frames StackFrame buffer, or null + * + * @return the end index to the frame buffers + */ + private native int fetchStackFrames(long mode, long anchor, + int batchSize, int startIndex, + Class[] classes, + StackFrame[] frames); + + + /* + * Frame buffer + * + * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer. + */ + class FrameBuffer { + static final int START_POS = 2; // 0th and 1st elements are reserved + + // buffers for VM to fill stack frame info + int currentBatchSize; // current batch size + Class[] classes; // caller class for fast path + + StackFrame[] stackFrames; + + int origin; // index to the current traversed stack frame + int fence; // index to the last frame in the current batch + + FrameBuffer(int initialBatchSize) { + if (initialBatchSize < MIN_BATCH_SIZE) { + throw new IllegalArgumentException(initialBatchSize + " < minimum batch size: " + MIN_BATCH_SIZE); + } + this.origin = START_POS; + this.fence = 0; + this.currentBatchSize = initialBatchSize; + this.classes = new Class[currentBatchSize]; + } + + int curBatchFrameCount() { + return currentBatchSize-START_POS; + } + + /* + * Tests if this frame buffer is empty. All frames are fetched. + */ + final boolean isEmpty() { + return origin >= fence || (origin == START_POS && fence == 0); + } + + /* + * Freezes this frame buffer. The stack stream source is done fetching. + */ + final void freeze() { + origin = 0; + fence = 0; + } + + /* + * Tests if this frame buffer is active. It is inactive when + * it is done for traversal. All stack frames have been traversed. + */ + final boolean isActive() { + return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize); + } + + /** + * Gets the class at the current frame and move to the next frame. + */ + final Class next() { + if (isEmpty()) { + throw new NoSuchElementException("origin=" + origin + " fence=" + fence); + } + Class c = classes[origin++]; + if (isDebug) { + int index = origin-1; + System.out.format(" next frame at %d: %s (origin %d fence %d)%n", index, + Objects.toString(c), index, fence); + } + return c; + } + + /** + * Gets the class at the current frame. + */ + final Class get() { + if (isEmpty()) { + throw new NoSuchElementException("origin=" + origin + " fence=" + fence); + } + return classes[origin]; + } + + /* + * Returns the index of the current frame. + */ + final int getIndex() { + return origin; + } + + /* + * Set the start and end index of a new batch of stack frames that have + * been filled in this frame buffer. + */ + final void setBatch(int startIndex, int endIndex) { + if (startIndex <= 0 || endIndex <= 0) + throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex); + + this.origin = startIndex; + this.fence = endIndex; + if (depth == 0 && fence > 0) { + // filter the frames due to the stack stream implementation + for (int i = START_POS; i < fence; i++) { + Class c = classes[i]; + if (isDebug) System.err.format(" frame %d: %s%n", i, c); + if (filterStackWalkImpl(c)) { + origin++; + } else { + break; + } + } + } + } + + /* + * Checks if the origin is the expected start index. + */ + final void check(int skipFrames) { + int index = skipFrames + START_POS; + if (origin != index) { + // stack walk must continue with the previous frame depth + throw new IllegalStateException("origin " + origin + " != " + index); + } + } + + // ------ subclass may override the following methods ------- + /** + * Resizes the buffers for VM to fill in the next batch of stack frames. + * The next batch will start at the given startIndex with the maximum number + * of elements. + * + *

Subclass may override this method to manage the allocated buffers. + * + * @param startIndex the start index for the first frame of the next batch to fill in. + * @param elements the number of elements for the next batch to fill in. + * + */ + void resize(int startIndex, int elements) { + if (!isActive()) + throw new IllegalStateException("inactive frame buffer can't be resized"); + + int size = startIndex+elements; + if (classes.length < size) { + // copy the elements in classes array to the newly allocated one. + // classes[0] is a Thread object + Class[] prev = classes; + classes = new Class[size]; + System.arraycopy(prev, 0, classes, 0, START_POS); + } + currentBatchSize = size; + } + + /* + * Returns the start index for this frame buffer is refilled. + * + * This implementation reuses the allocated buffer for the next batch + * of stack frames. For subclass to retain the fetched stack frames, + * it should override this method to return the index at which the frame + * should be filled in for the next batch. + */ + int startIndex() { + return START_POS; + } + + /** + * Returns next StackFrame object in the current batch of stack frames + */ + StackFrame nextStackFrame() { + throw new InternalError("should not reach here"); + } + } + } + + /* + * This StackFrameTraverser supports {@link Stream} traversal. + * + * This class implements Spliterator::forEachRemaining and Spliterator::tryAdvance. + */ + static class StackFrameTraverser extends AbstractStackWalker + implements Spliterator + { + static { + stackWalkImplClasses.add(StackFrameTraverser.class); + } + private static final int CHARACTERISTICS = Spliterator.ORDERED | Spliterator.IMMUTABLE; + class Buffer extends FrameBuffer { + Buffer(int initialBatchSize) { + super(initialBatchSize); + + this.stackFrames = new StackFrame[initialBatchSize]; + for (int i = START_POS; i < initialBatchSize; i++) { + stackFrames[i] = new StackFrameInfo(walker); + } + } + + @Override + void resize(int startIndex, int elements) { + super.resize(startIndex, elements); + + int size = startIndex+elements; + if (stackFrames.length < size) { + stackFrames = new StackFrame[size]; + } + for (int i = startIndex(); i < size; i++) { + stackFrames[i] = new StackFrameInfo(walker); + } + } + + @Override + StackFrame nextStackFrame() { + if (isEmpty()) { + throw new NoSuchElementException("origin=" + origin + " fence=" + fence); + } + + StackFrame frame = stackFrames[origin]; + origin++; + return frame; + } + } + + final Function, ? extends T> function; // callback + + StackFrameTraverser(StackWalker walker, + Function, ? extends T> function) { + this(walker, function, DEFAULT_MODE); + } + StackFrameTraverser(StackWalker walker, + Function, ? extends T> function, + int mode) { + super(walker, mode); + this.function = function; + } + + /** + * Returns next StackFrame object in the current batch of stack frames; + * or null if no more stack frame. + */ + StackFrame nextStackFrame() { + if (!hasNext()) { + return null; + } + + StackFrame frame = frameBuffer.nextStackFrame(); + depth++; + return frame; + } + + @Override + protected T consumeFrames() { + checkState(OPEN); + Stream stream = StreamSupport.stream(this, false); + if (function != null) { + return function.apply(stream); + } else + throw new UnsupportedOperationException(); + } + + @Override + protected void initFrameBuffer() { + this.frameBuffer = new Buffer(getNextBatchSize()); + } + + @Override + protected int batchSize(int lastBatchFrameCount) { + if (lastBatchFrameCount == 0) { + // First batch, use estimateDepth if not exceed the large batch size + // and not too small + int initialBatchSize = Math.max(walker.estimateDepth(), SMALL_BATCH); + return Math.min(initialBatchSize, LARGE_BATCH_SIZE); + } else { + if (lastBatchFrameCount > BATCH_SIZE) { + return lastBatchFrameCount; + } else { + return Math.min(lastBatchFrameCount*2, BATCH_SIZE); + } + } + } + + // ------- Implementation of Spliterator + + @Override + public Spliterator trySplit() { + return null; // ordered stream and do not allow to split + } + + @Override + public long estimateSize() { + return maxDepth; + } + + @Override + public int characteristics() { + return CHARACTERISTICS; + } + + @Override + public void forEachRemaining(Consumer action) { + checkState(OPEN); + for (int n = 0; n < maxDepth; n++) { + StackFrame frame = nextStackFrame(); + if (frame == null) break; + + action.accept(frame); + } + } + + @Override + public boolean tryAdvance(Consumer action) { + checkState(OPEN); + + int index = frameBuffer.getIndex(); + if (hasNext()) { + StackFrame frame = nextStackFrame(); + action.accept(frame); + if (isDebug) { + System.err.println("tryAdvance: " + index + " " + frame); + } + return true; + } + if (isDebug) { + System.err.println("tryAdvance: " + index + " NO element"); + } + return false; + } + } + + /* + * CallerClassFinder is specialized to return Class for each stack frame. + * StackFrame is not requested. + */ + static class CallerClassFinder extends AbstractStackWalker { + static { + stackWalkImplClasses.add(CallerClassFinder.class); + } + + private Class caller; + + CallerClassFinder(StackWalker walker) { + super(walker, FILL_CLASS_REFS_ONLY); + } + + Class findCaller() { + walk(); + return caller; + } + + @Override + protected Integer consumeFrames() { + checkState(OPEN); + int n = 0; + Class[] frames = new Class[2]; + // skip the API calling this getCallerClass method + // 0: StackWalker::getCallerClass + // 1: caller-sensitive method + // 2: caller class + while (n < 2 && (caller = nextFrame()) != null) { + if (isMethodHandleFrame(caller)) continue; + frames[n++] = caller; + } + + if (frames[1] == null) + throw new IllegalStateException("no caller frame"); + return n; + } + + @Override + protected void initFrameBuffer() { + this.frameBuffer = new FrameBuffer(getNextBatchSize()); + } + + @Override + protected int batchSize(int lastBatchFrameCount) { + return MIN_BATCH_SIZE; + } + + @Override + protected int getNextBatchSize() { + return MIN_BATCH_SIZE; + } + } + + /* + * StackTrace caches all frames in the buffer. StackTraceElements are + * created lazily when Throwable::getStackTrace is called. + */ + static class StackTrace extends AbstractStackWalker { + static { + stackWalkImplClasses.add(StackTrace.class); + } + + class GrowableBuffer extends FrameBuffer { + GrowableBuffer(int initialBatchSize) { + super(initialBatchSize); + + this.stackFrames = new StackFrame[initialBatchSize]; + for (int i = START_POS; i < initialBatchSize; i++) { + stackFrames[i] = new StackFrameInfo(walker); + } + } + + /* + * Returns the next index to fill + */ + @Override + int startIndex() { + return origin; + } + + /** + * Initialize the buffers for VM to fill in the stack frame information. + * The next batch will start at the given startIndex to + * the length of the buffer. + */ + @Override + void resize(int startIndex, int elements) { + // Expand the frame buffer. + // Do not call super.resize that will reuse the filled elements + // in this frame buffer + int size = startIndex+elements; + if (classes.length < size) { + // resize the frame buffer + classes = Arrays.copyOf(classes, size); + stackFrames = Arrays.copyOf(stackFrames, size); + } + for (int i = startIndex; i < size; i++) { + stackFrames[i] = new StackFrameInfo(walker); + } + currentBatchSize = size; + } + + StackTraceElement get(int index) { + return new StackTraceElement(classes[index].getName(), "unknown", null, -1); + } + + /** + * Returns an array of StackTraceElement for all stack frames cached in + * this StackTrace object. + *

+ * This method is intended for Throwable::getOurStackTrace use only. + */ + StackTraceElement[] toStackTraceElements() { + int startIndex = START_POS; + for (int i = startIndex; i < classes.length; i++) { + if (classes[i] != null && filterStackWalkImpl(classes[i])) { + startIndex++; + } else { + break; + } + } + + // VM fills in the method name, filename, line number info + StackFrameInfo.fillInStackFrames(0, stackFrames, startIndex, startIndex + depth); + + StackTraceElement[] stes = new StackTraceElement[depth]; + for (int i = startIndex, j = 0; i < classes.length && j < depth; i++, j++) { + if (isDebug) { + System.err.println("StackFrame: " + i + " " + stackFrames[i]); + } + stes[j] = stackFrames[i].toStackTraceElement(); + } + return stes; + } + } + + private static final int MAX_STACK_FRAMES = 1024; + private static final StackWalker STACKTRACE_WALKER = + StackWalker.newInstanceNoCheck(EnumSet.of(Option.SHOW_REFLECT_FRAMES)); + + private StackTraceElement[] stes; + static StackTrace dump() { + return new StackTrace(); + } + + static StackTrace dump(Throwable ex) { + return new StackTrace(ex); + } + + private StackTrace() { + this(STACKTRACE_WALKER, DEFAULT_MODE); + } + + /* + * Throwable::fillInStackTrace and of Throwable and subclasses + * are filtered in the VM. + */ + private StackTrace(Throwable ex) { + this(STACKTRACE_WALKER, FILTER_FILL_IN_STACKTRACE); // skip Throwable::init frames + if (isDebug) { + System.err.println("dump stack for " + ex.getClass().getName()); + } + } + + StackTrace(StackWalker walker, int mode) { + super(walker, mode, MAX_STACK_FRAMES); + + // snapshot the stack trace + walk(); + } + + @Override + protected Integer consumeFrames() { + // traverse all frames and perform the action on the stack frames, if specified + int n = 0; + while (n < maxDepth && nextFrame() != null) { + n++; + } + return n; + } + + @Override + protected void initFrameBuffer() { + this.frameBuffer = new GrowableBuffer(getNextBatchSize()); + } + + // TODO: implement better heuristic + @Override + protected int batchSize(int lastBatchFrameCount) { + // chunk size of VM backtrace is 32 + return lastBatchFrameCount == 0 ? 32 : 32; + } + + /** + * Returns an array of StackTraceElement for all stack frames cached in + * this StackTrace object. + *

+ * This method is intended for Throwable::getOurStackTrace use only. + */ + synchronized StackTraceElement[] getStackTraceElements() { + if (stes == null) { + stes = ((GrowableBuffer) frameBuffer).toStackTraceElements(); + // release the frameBuffer memory + frameBuffer = null; + } + return stes; + } + + /* + * Prints stack trace to the given PrintStream. + * + * Further implementation could skip creating StackTraceElement objects + * print directly to the PrintStream. + */ + void printStackTrace(PrintStream s) { + StackTraceElement[] stes = getStackTraceElements(); + synchronized (s) { + s.println("Stack trace"); + for (StackTraceElement traceElement : stes) + s.println("\tat " + traceElement); + } + } + } + + static class LiveStackInfoTraverser extends StackFrameTraverser { + static { + stackWalkImplClasses.add(LiveStackInfoTraverser.class); + } + // VM will fill in all method info and live stack info directly in StackFrameInfo + class Buffer extends FrameBuffer { + Buffer(int initialBatchSize) { + super(initialBatchSize); + this.stackFrames = new StackFrame[initialBatchSize]; + for (int i = START_POS; i < initialBatchSize; i++) { + stackFrames[i] = new LiveStackFrameInfo(walker); + } + } + + @Override + void resize(int startIndex, int elements) { + super.resize(startIndex, elements); + int size = startIndex + elements; + + if (stackFrames.length < size) { + this.stackFrames = new StackFrame[size]; + } + + for (int i = startIndex(); i < size; i++) { + stackFrames[i] = new LiveStackFrameInfo(walker); + } + } + + @Override + StackFrame nextStackFrame() { + if (isEmpty()) { + throw new NoSuchElementException("origin=" + origin + " fence=" + fence); + } + + StackFrame frame = stackFrames[origin]; + origin++; + return frame; + } + } + + LiveStackInfoTraverser(StackWalker walker, + Function, ? extends T> function) { + super(walker, function, DEFAULT_MODE); + } + + @Override + protected void initFrameBuffer() { + this.frameBuffer = new Buffer(getNextBatchSize()); + } + } + + private static native boolean checkStackWalkModes(); + + // avoid loading other subclasses as they may not be used + private static Set> init() { + if (!checkStackWalkModes()) { + throw new InternalError("StackWalker mode values do not match with JVM"); + } + + Set> classes = new HashSet<>(); + classes.add(StackWalker.class); + classes.add(StackStreamFactory.class); + classes.add(AbstractStackWalker.class); + return classes; + } + + private static boolean filterStackWalkImpl(Class c) { + return stackWalkImplClasses.contains(c) || + c.getName().startsWith("java.util.stream."); + } + + // MethodHandle frames are not hidden and CallerClassFinder has + // to filter them out + private static boolean isMethodHandleFrame(Class c) { + return c.getName().startsWith("java.lang.invoke."); + } + + private static boolean isReflectionFrame(Class c) { + if (c.getName().startsWith("sun.reflect") && + !sun.reflect.MethodAccessor.class.isAssignableFrom(c)) { + throw new InternalError("Not sun.reflect.MethodAccessor: " + c.toString()); + } + // ## should filter all @Hidden frames? + return c == Method.class || + sun.reflect.MethodAccessor.class.isAssignableFrom(c) || + c.getName().startsWith("java.lang.invoke.LambdaForm"); + } + + private static boolean getProperty(String key, boolean value) { + String s = AccessController.doPrivileged(new PrivilegedAction<>() { + @Override + public String run() { + return System.getProperty(key); + } + }); + if (s != null) { + return Boolean.valueOf(s); + } + return value; + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/StackWalker.java b/jdk/src/java.base/share/classes/java/lang/StackWalker.java new file mode 100644 index 00000000000..ec5e581b7a6 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/StackWalker.java @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2015, 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 java.lang; + +import sun.reflect.CallerSensitive; + +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * A stack walker. + * + *

The {@link StackWalker#walk walk} method opens a sequential stream + * of {@link StackFrame StackFrame}s for the current thread and then applies + * the given function to walk the {@code StackFrame} stream. + * The stream reports stack frame elements in order, from the top most frame + * that represents the execution point at which the stack was generated to + * the bottom most frame. + * The {@code StackFrame} stream is closed when the {@code walk} method returns. + * If an attempt is made to reuse the closed stream, + * {@code IllegalStateException} will be thrown. + * + *

The {@linkplain Option stack walking options} of a + * {@code StackWalker} determines the information of + * {@link StackFrame StackFrame} objects to be returned. + * By default, stack frames of the reflection API and implementation + * classes are {@linkplain Option#SHOW_HIDDEN_FRAMES hidden} + * and {@code StackFrame}s have the class name and method name + * available but not the {@link StackFrame#getDeclaringClass() Class reference}. + * + *

{@code StackWalker} is thread-safe. Multiple threads can share + * a single {@code StackWalker} object to traverse its own stack. + * A permission check is performed when a {@code StackWalker} is created, + * according to the options it requests. + * No further permission check is done at stack walking time. + * + * @apiNote + * Examples + * + *

1. To find the first caller filtering a known list of implementation class: + *

{@code
+ *     StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
+ *     Optional> callerClass = walker.walk(s ->
+ *         s.map(StackFrame::getDeclaringClass)
+ *          .filter(interestingClasses::contains)
+ *          .findFirst());
+ * }
+ * + *

2. To snapshot the top 10 stack frames of the current thread, + *

{@code
+ *     List stack = StackWalker.getInstance().walk(s ->
+ *         s.limit(10).collect(Collectors.toList()));
+ * }
+ * + * Unless otherwise noted, passing a {@code null} argument to a + * constructor or method in this {@code StackWalker} class + * will cause a {@link NullPointerException NullPointerException} + * to be thrown. + * + * @since 1.9 + */ +public final class StackWalker { + /** + * A {@code StackFrame} object represents a method invocation returned by + * {@link StackWalker}. + * + *

The {@link #getDeclaringClass()} method may be unsupported as determined + * by the {@linkplain Option stack walking options} of a {@linkplain + * StackWalker stack walker}. + * + * @since 1.9 + * @jvms 2.6 + */ + public static interface StackFrame { + /** + * Gets the binary name + * of the declaring class of the method represented by this stack frame. + * + * @return the binary name of the declaring class of the method + * represented by this stack frame + * + * @jls 13.1 The Form of a Binary + */ + public String getClassName(); + + /** + * Gets the name of the method represented by this stack frame. + * @return the name of the method represented by this stack frame + */ + public String getMethodName(); + + /** + * Gets the declaring {@code Class} for the method represented by + * this stack frame. + * + * @return the declaring {@code Class} of the method represented by + * this stack frame + * + * @throws UnsupportedOperationException if this {@code StackWalker} + * is not configured with {@link Option#RETAIN_CLASS_REFERENCE + * Option.RETAIN_CLASS_REFERENCE}. + */ + public Class getDeclaringClass(); + + /** + * Returns the name of the source file containing the execution point + * represented by this stack frame. Generally, this corresponds + * to the {@code SourceFile} attribute of the relevant {@code class} + * file as defined by The Java Virtual Machine Specification. + * In some systems, the name may refer to some source code unit + * other than a file, such as an entry in a source repository. + * + * @return the name of the file containing the execution point + * represented by this stack frame, or empty {@code Optional} + * is unavailable. + * + * @jvms 4.7.10 The {@code SourceFile} Attribute + */ + public Optional getFileName(); + + /** + * Returns the line number of the source line containing the execution + * point represented by this stack frame. Generally, this is + * derived from the {@code LineNumberTable} attribute of the relevant + * {@code class} file as defined by The Java Virtual Machine + * Specification. + * + * @return the line number of the source line containing the execution + * point represented by this stack frame, or empty + * {@code Optional} if this information is unavailable. + * + * @jvms 4.7.12 The {@code LineNumberTable} Attribute + */ + public OptionalInt getLineNumber(); + + /** + * Returns {@code true} if the method containing the execution point + * represented by this stack frame is a native method. + * + * @return {@code true} if the method containing the execution point + * represented by this stack frame is a native method. + */ + public boolean isNativeMethod(); + + /** + * Gets a {@code StackTraceElement} for this stack frame. + * + * @return {@code StackTraceElement} for this stack frame. + * + * */ + public default StackTraceElement toStackTraceElement() { + int lineNumber = isNativeMethod() ? -2 + : getLineNumber().orElse(-1); + return new StackTraceElement(getClassName(), getMethodName(), + getFileName().orElse(null), + lineNumber); + } + } + + /** + * Stack walker option to configure the {@linkplain StackFrame stack frame} + * information obtained by a {@code StackWalker}. + * + * @since 1.9 + */ + public enum Option { + /** + * Retains {@code Class} object in {@code StackFrame}s + * walked by this {@code StackWalker}. + * + *

A {@code StackWalker} configured with this option will support + * {@link StackWalker#getCallerClass()} and + * {@link StackFrame#getDeclaringClass() StackFrame.getDeclaringClass()}. + */ + RETAIN_CLASS_REFERENCE, + /** + * Shows all reflection frames. + * + *

By default, reflection frames are hidden. This includes the + * {@link java.lang.reflect.Method#invoke} method + * and the reflection implementation classes. A {@code StackWalker} with + * this {@code SHOW_REFLECT_FRAMES} option will show all reflection frames. + * The {@link #SHOW_HIDDEN_FRAMES} option can also be used to show all + * reflection frames and it will also show other hidden frames that + * are implementation-specific. + */ + SHOW_REFLECT_FRAMES, + /** + * Shows all hidden frames. + * + *

A Java Virtual Machine implementation may hide implementation + * specific frames in addition to {@linkplain #SHOW_REFLECT_FRAMES + * reflection frames}. A {@code StackWalker} with this {@code SHOW_HIDDEN_FRAMES} + * option will show all hidden frames (including reflection frames). + */ + SHOW_HIDDEN_FRAMES; + } + + enum ExtendedOption { + /** + * Obtain monitors, locals and operands. + */ + LOCALS_AND_OPERANDS + }; + + static final EnumSet

This {@code StackWalker} is configured to skip all + * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and + * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained. + * + * @return a {@code StackWalker} configured to skip all + * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and + * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained. + * + */ + public static StackWalker getInstance() { + // no permission check needed + return DEFAULT_WALKER; + } + + /** + * Returns a {@code StackWalker} instance with the given option specifying + * the stack frame information it can access. + * + *

+ * If a security manager is present and the given {@code option} is + * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE}, + * it calls its {@link SecurityManager#checkPermission checkPermission} + * method for {@code StackFramePermission("retainClassReference")}. + * + * @param option {@link Option stack walking option} + * + * @return a {@code StackWalker} configured with the given option + * + * @throws SecurityException if a security manager exists and its + * {@code checkPermission} method denies access. + */ + public static StackWalker getInstance(Option option) { + return getInstance(EnumSet.of(Objects.requireNonNull(option))); + } + + /** + * Returns a {@code StackWalker} instance with the given {@code options} specifying + * the stack frame information it can access. If the given {@code options} + * is empty, this {@code StackWalker} is configured to skip all + * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no + * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained. + * + *

+ * If a security manager is present and the given {@code options} contains + * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE}, + * it calls its {@link SecurityManager#checkPermission checkPermission} + * method for {@code StackFramePermission("retainClassReference")}. + * + * @param options {@link Option stack walking option} + * + * @return a {@code StackWalker} configured with the given options + * + * @throws SecurityException if a security manager exists and its + * {@code checkPermission} method denies access. + */ + public static StackWalker getInstance(Set

+ * If a security manager is present and the given {@code options} contains + * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE}, + * it calls its {@link SecurityManager#checkPermission checkPermission} + * method for {@code StackFramePermission("retainClassReference")}. + * + *

+ * The {@code estimateDepth} specifies the estimate number of stack frames + * this {@code StackWalker} will traverse that the {@code StackWalker} could + * use as a hint for the buffer size. + * + * @param options {@link Option stack walking options} + * @param estimateDepth Estimate number of stack frames to be traversed. + * + * @return a {@code StackWalker} configured with the given options + * + * @throws IllegalArgumentException if {@code estimateDepth <= 0} + * @throws SecurityException if a security manager exists and its + * {@code checkPermission} method denies access. + */ + public static StackWalker getInstance(Set

The {@code StackFrame} stream will be closed when + * this method returns. When a closed {@code Stream} object + * is reused, {@code IllegalStateException} will be thrown. + * + * @apiNote + * For example, to find the first 10 calling frames, first skipping those frames + * whose declaring class is in package {@code com.foo}: + *

+ *
{@code
+     * List frames = StackWalker.getInstance().walk(s ->
+     *     s.dropWhile(f -> f.getClassName().startsWith("com.foo."))
+     *      .limit(10)
+     *      .collect(Collectors.toList()));
+     * }
+ * + *

This method takes a {@code Function} accepting a {@code Stream}, + * rather than returning a {@code Stream} and allowing the + * caller to directly manipulate the stream. The Java virtual machine is + * free to reorganize a thread's control stack, for example, via + * deoptimization. By taking a {@code Function} parameter, this method + * allows access to stack frames through a stable view of a thread's control + * stack. + * + *

Parallel execution is effectively disabled and stream pipeline + * execution will only occur on the current thread. + * + * @implNote The implementation stabilizes the stack by anchoring a frame + * specific to the stack walking and ensures that the stack walking is + * performed above the anchored frame. When the stream object is closed or + * being reused, {@code IllegalStateException} will be thrown. + * + * @param function a function that takes a stream of + * {@linkplain StackFrame stack frames} and returns a result. + * @param The type of the result of applying the function to the + * stream of {@linkplain StackFrame stack frame}. + * + * @return the result of applying the function to the stream of + * {@linkplain StackFrame stack frame}. + */ + @CallerSensitive + public T walk(Function, ? extends T> function) { + // Returning a Stream would be unsafe, as the stream could + // be used to access the stack frames in an uncontrolled manner. For + // example, a caller might pass a Spliterator of stack frames after one + // or more frames had been traversed. There is no robust way to detect + // whether the execution point when + // Spliterator.tryAdvance(java.util.function.Consumer) is + // invoked is the exact same execution point where the stack frame + // traversal is expected to resume. + + Objects.requireNonNull(function); + return StackStreamFactory.makeStackTraverser(this, function) + .walk(); + } + + /** + * Performs the given action on each element of {@code StackFrame} stream + * of the current thread, traversing from the top frame of the stack, + * which is the method calling this {@code forEach} method. + * + *

This method is equivalent to calling + *

+ * {@code walk(s -> { s.forEach(action); return null; });} + *
+ * + * @param action an action to be performed on each {@code StackFrame} + * of the stack of the current thread + */ + @CallerSensitive + public void forEach(Consumer action) { + Objects.requireNonNull(action); + StackStreamFactory.makeStackTraverser(this, s -> { + s.forEach(action); + return null; + }).walk(); + } + + /** + * Gets the {@code Class} object of the caller invoking the method + * that calls this {@code getCallerClass} method. + * + *

Reflection frames, {@link java.lang.invoke.MethodHandle} and + * hidden frames are filtered regardless of the + * {@link Option#SHOW_REFLECT_FRAMES SHOW_REFLECT_FRAMES} + * and {@link Option#SHOW_HIDDEN_FRAMES SHOW_HIDDEN_FRAMES} options + * this {@code StackWalker} has been configured. + * + *

This method throws {@code UnsupportedOperationException} + * if this {@code StackWalker} is not configured with + * {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option, + * This method should be called when a caller frame is present. If + * it is called from the last frame on the stack; + * {@code IllegalStateException} will be thrown. + * + * @apiNote + * For example, {@code Util::getResourceBundle} loads a resource bundle + * on behalf of the caller. It calls this {@code getCallerClass} method + * to find the method calling {@code Util::getResourceBundle} and use the caller's + * class loader to load the resource bundle. The caller class in this example + * is the {@code MyTool} class. + * + *

{@code
+     * class Util {
+     *     private final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
+     *     public ResourceBundle getResourceBundle(String bundleName) {
+     *         Class caller = walker.getCallerClass();
+     *         return ResourceBundle.getBundle(bundleName, Locale.getDefault(), caller.getClassLoader());
+     *     }
+     * }
+     *
+     * class MyTool {
+     *     private final Util util = new Util();
+     *     private void init() {
+     *         ResourceBundle rb = util.getResourceBundle("mybundle");
+     *     }
+     * }
+     * }
+ * + * An equivalent way to find the caller class using the + * {@link StackWalker#walk walk} method is as follows + * (filtering the reflection frames, {@code MethodHandle} and hidden frames + * not shown below): + *
{@code
+     *     Optional> caller = walker.walk(s ->
+     *         s.map(StackFrame::getDeclaringClass)
+     *          .skip(2)
+     *          .findFirst());
+     * }
+ * + * When the {@code getCallerClass} method is called from a method that + * is the last frame on the stack, + * for example, {@code static public void main} method launched by the + * {@code java} launcher or a method invoked from a JNI attached thread. + * {@code IllegalStateException} is thrown. + * + * @return {@code Class} object of the caller's caller invoking this method. + * + * @throws UnsupportedOperationException if this {@code StackWalker} + * is not configured with {@link Option#RETAIN_CLASS_REFERENCE + * Option.RETAIN_CLASS_REFERENCE}. + * @throws IllegalStateException if there is no caller frame, i.e. + * when this {@code getCallerClass} method is called from a method + * which is the last frame on the stack. + */ + @CallerSensitive + public Class getCallerClass() { + if (!options.contains(Option.RETAIN_CLASS_REFERENCE)) { + throw new UnsupportedOperationException("This stack walker " + + "does not have RETAIN_CLASS_REFERENCE access"); + } + + return StackStreamFactory.makeCallerFinder(this).findCaller(); + } + + // ---- package access ---- + static StackWalker newInstanceNoCheck(EnumSet