diff --git a/.hgtags b/.hgtags index 50c1586057db91e2c1beac5258a2de6f410df324..18e705aeb10c6255cfa31e339e38418e1bb51ff6 100644 --- a/.hgtags +++ b/.hgtags @@ -334,3 +334,4 @@ f61a63b7d1e52e307abc0bfc751203155d362ec4 jdk9-b83 4a0312f2894bcbe1fd20266c8fda8d983bd2fcf6 jdk9-b89 d131f4b8433a79408f935eff9bf92a0664229b60 jdk9-b90 8077fd2f055d31e50b46fcf62d9c035bc385a215 jdk9-b91 +f242d4332f563648426a1b0fa02d8741beba19ef jdk9-b92 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 77827b83110e0a282a65060e6e6f8511067351d2..d1d6793cbff809f15ab31e9062f868c90502c25b 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -334,3 +334,4 @@ fd4f4f7561074dc0dbc1772c8489c7b902b6b8a9 jdk9-b87 895353113f382d24e623191fdab0e29a3ce34738 jdk9-b89 cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90 122142a185381ce5cea959bf13b923d8cc333628 jdk9-b91 +106c06398f7ab330eef9e335fbd3a5a8ead23b77 jdk9-b92 diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 9fd553f0d867b8d6850658992ea643299fa76bf4..eb053466068071e2c6be7666b022d7f4dbedde92 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 383f359fad314375858e225c806d0589e2dc040d..b44c78e430044b77bf515afcb8dc4bec4e77dc2e 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 18e11b034c8f217c5f512f06986e915fe12aef77..1b2781266445c34f2bb71492d95ce3b4ce5a35de 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 ccf778795086cf4923a1c10b641394b9cc24be27..7c1492ed24c66497755be641fa821f389726482e 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 d8212483ec9ea40afa31c2dd02f845e5ef0671e9..0be7456fa2c5c97f14fc76063e65ffa90fddd358 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 32f4881f60802631b11d07c91b9b46f6ecb755eb..18924c92be7fbe5bcea380b0c52c4cc935e480d0 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 6d0a137add803337978bddcb35fbb7e769df62cf..2bf4cc30cb4b191885a6636d012f3a212f3aad09 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -334,3 +334,4 @@ a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87 c847a53b38d2fffb87afc483c74db05eced9b4f4 jdk9-b89 29cc8228d62319af21cad7c90817671e0813b6bd jdk9-b90 75843e0a9371d445a3c9b440bab85e50b5dc287c jdk9-b91 +f7d70caad89ad0c43bb057bca0aad6f17ce05a6a jdk9-b92 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 c6eb5f7051a73803c95672dc76d862f05f5e7116..3c357f61c38eb41f689e9f8a41b67f34b032c2c3 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 24996d51ed03bce63d93bda947aae8a872ab26db..d9dceac7ba8d963381d6aafd3e0fc1bb264d6b55 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 d10f4e3eccd3b2b8fbcd6bee28f569af422f0511..546914d623d8139e8a212f81612f17cb369182a9 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 41100a4b3bdc0e5529b6f0306b7c8d5bd887d13e..22610dda9babb88c09c9623e28d377c05a0430ef 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 21a5c3406129f50407323faf75dba4d482cbf765..9e9fce8a47df302e82aea15cfdcc984cf1b3ff99 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 bb67c3cd6547079a702be325069419eb3b95a132..82da35a79214bf4732bc1f20c08c504b2d57adb1 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 12a8127d0613e43334e7ebc0c19bcdcd51f6217b..9a0e56afc4f66463bea63f89930c7337c57c6cbc 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 b888de302283a81928b3f733f4f5d95fee66ba89..0000000000000000000000000000000000000000 --- 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<Unsafe> 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<Long> 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 4acac0a176e5b2d500a6b14e25f210670463749c..c43c1dfa7b510fb7ba7d5aa5a61817c12943af0d 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 987ee0973763e04fac0888f66659a403f532ee83..1891612219c1302d997217e1f3093325b0d40686 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 b4c56080f9fe457ebec3f0e617c81f6582d053b6..19ff5bddcfa6520d068c61ac8ba1580d1b7d9f71 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<Unsafe> 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 d9bdc622912b5ed366b7661f3a5634193514a9c4..8bd4af0eb822b267ed1196ad3a9c7c341f7181ef 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 430d279731b9d5ba4b25422f1daace5f5ed9f0ee..1a17516ef3d8e542b773f559e6e84c02b787738d 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -494,3 +494,4 @@ bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88 20dff0211deda8d5877fda0e80b6d165ab93c6c2 jdk9-b89 7fe46dc64bb3a8df554b24cde0153ffb24f39c5e jdk9-b90 3fd5c2ca4c20c183628b6dbeb8df821a961419e3 jdk9-b91 +53cb98d68a1aeb08d29c89d6da748de60c448e37 jdk9-b92 diff --git a/hotspot/agent/src/os/linux/symtab.c b/hotspot/agent/src/os/linux/symtab.c index 61c987478549529bd6abf52117d29a3f7ece0302..1c96cf3e3700cdd72fb3454569ec16a89e229fd0 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 ef8a7e1849ebb6ff738d5094c672642d26adaeab..3afdab8a76116be23e0c1af48825829f9f56642b 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"); - } - } - if (offsetField != null && countField != null) { - return charArrayToString((TypeArray) valueField.getValue(stringOop), - offsetField.getValue(stringOop), - countField.getValue(stringOop)); + 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"); } - 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 f10e0b4c41848236c94ce3f6dbf8ab3d39000297..893c5e1e31b26db97e307e914590c88cc32bad46 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 e2281e7b321d0cd2e5456cfad77b325a8888b513..ea4fa581a8ec7f8a004ec6104125b72b4387f729 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 6475b29b255b5d95aa25bc2c516f3baf14e9f334..cf1a4167e18a5af4713dafc337f6153bd2f66001 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/bsd/makefiles/buildtree.make b/hotspot/make/bsd/makefiles/buildtree.make index b1f9e02f3c342a3bc6c8d0b6597993256bf96d21..e48d6aba1044d626b1255555ae34bad1d093a376 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 74f2fedd8b7fc91d1791122dee50007399cc2f2d..a418eeb8e1dc94dee7d2f54929cc2e717486d58c 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 c506679b1f838b945795b2dd1b2465002714e963..e2af31ea7a02d258c03bc481c1a04682226667ba 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 60187bdc27f4e67ccfc9789cdd657f0b06f085f1..fc7b25fceaa9f2b2d9192d6124ff1f523961e8f8 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 6a9cebbb3371267ebb88168ac7cf292951311707..585a0f45ba976dcd3ef0a62dcd3b335d20b69afe 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/rules.make b/hotspot/make/bsd/makefiles/rules.make index 2c4c38658c6b73465cc7b98ebb217715816bdebd..d2334a70ffb57bbfb821fe5c90a5c8573bf43452 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 8c7545a5ee78c09aeed30f3bd4076f7a3b8e933b..c1783c470a7d32975e3db5d62c0b1b273738ef69 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/vm.make b/hotspot/make/bsd/makefiles/vm.make index 562d1f45729d72c5340e4e56635e51a979280682..71012e96193dc07209dc1bde4e47067fea6dcaa6 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 123d3882d42e611f20192d7fe45340c68a696690..654a7f8fd32613fdec960649aad8c10c2a4b120c 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/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index 3ed22a1da8c1f11df8bed1700298310364601303..7920596193f96c05e9cdead2e18df82c0e65bd05 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/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index dabc578fe08a247f620037dc0486585120b2d915..0861f782775207b6ad61cdcbeb4d28d837a944d2 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 907370d13859be9ee85c784fe64ec4e681032e58..119d113aac54b632a174879d584638a7bd985a29 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 6f213f20a2440b1138909a11bd74c42c66446543..0182af2400f5685d5ad07547eb6199f5d8210a48 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 c9467bfb23cb069180b8b68a3fe41d39503bf5dc..f68c3e854da3595d2710653e0ff828daf46c16ef 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 ba8c3cc31b907e810077f36519c8fb3c31dba744..dedabb6729be1a40a8fd1015680769aa85f86678 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 ef7cacae7a92e708f1909264aad26e9ba55d0453..b22e5789380dc306cf4c9d554cb5ec2fdbd16709 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 fac126363a0d88ce72430e8f2bea9fb9edf2b69a..e1a5293a82687312fe5bcf2744914b01468b1b64 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 cab965e3cc9ff20f55bd98b49802dc4fe74aef88..13185cc36bf4764c1c08253edf44209e7bf9474c 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 980c043f9e78438ebdf50f44ab9718e72364ea95..fed5e53c2063e4bef5d0c28180856debaf68c4e6 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 d5f6486056be6964055e8ddb2c5d93d9f80a12a5..fd4a6de1869d98d59c5a424ea237261162d33a3c 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. @@ -11077,7 +11077,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 +11120,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 +11167,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 +11200,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 +11224,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 +11247,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 +11267,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/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index e6853776063fb186b0459facc258630aea3d6976..e89c578e9e753e4c144d83e70bf515e24287a3d2 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 d4fd95ebce10a669f90a6d7954a04d1a5eeccdc7..e2ef96c727c05089333933810b1a7a918b4e4020 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 6efec095dccfcc4d80c3fccd6500913e959c8f0c..496c9e914da877af98dcd904a7e1b13dcf71e1e8 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 36f660b554b6cee112db7dc4f5025d101ffb6033..06867066fc1edb8481ee4aafb8e5024c9dd6d6a9 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 10da55791d3913354967f819a8ce94332a60c44a..45b27ab0a78d165c403a638e4a209608d4a6c33a 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 2647d327bd5f9374c041142eeae5e412af534e21..a6d5cd68e47689e3e5f4057628060468c50f7e49 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 + +// 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); - // Note: limit contains number of bytes (2*char_elements) != 0. - andcc(limit, 0x2, chr1); // trailing character ? + // 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 22f56b999bc3290b5692f1b101c03571f724bfc6..792a493bc014f9631b2a3660ceda562bf98f4744 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 5246059b4700836b9f18c0be9aed675113c7c369..4d51de2921a225c25800aa345daa04b7df844fcc 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 c7b89b110e90d1771c0147e3a1023ff802907036..cd41540d7c8956f90bf3f9765d25cbefe0e285e5 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp @@ -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 44e0470133eef2168b10a1ffabede47ce9bd66b6..a5f04a8f5b9b2cbf0929dd684f9d43e5309e432a 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/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index 449488b94c9c4b506755621234f27c6a3b1b5351..0c78b651e446417b04737dcc9c8e1f75421332f3 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 886a9c30d028765237e279d9fa2b49ba52f9a761..5d26b664175f1cd46028336cbd782518ca7aab50 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 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_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 $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} - ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) ); + 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 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 string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, - o7RegI tmp, 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 $str1,$str2,$cnt -> $result // KILL $tmp" %} - ins_encode( enc_String_Equals(str1, str2, cnt, result) ); + 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_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, - o7RegI tmp2, flagsReg ccr) %{ +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 e0be8b60ff9e5be18d0ac402f1130d28421d4428..24b008b4243b97728e78b5d5797c8a73e8ba176d 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 0d11387d411b8b161c5c085eb8031f7158dd311c..88db2698cda270283a1661ee148ecb6da655a030 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 db1afca3d4600ef43c07b514b92a789374cfeed0..28210a7af477d64a57517bd60bdec6e612a3e0cc 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 f09d6107092bb8fa8b7118b9d7532fa7b8245b86..bd7d145e99136235df098bc776ae87949a8e3c66 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 54ceb34cb72e2c59aa81f7d63656b8ba1a06d9de..9933655cdbab7d72c74ac3fa63367eec529e167c 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 fe81aac91f465d5fc6af3d26ce80890063715066..43c4cca5b2ae8084d29994794f17c8d8fcf8953d 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 e4fb943a925dc10bf8adf1827f0c52f43b79c925..a45e0eb9aa3dff844cad2d813ddb6bee2ec0982c 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 1f523c7621d197768cb7a4248f264f0d03068213..7286fd124b83a7cc8aa054a9ea836d4ae9b607a9 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 6b467b1110bfed5ce96fc8ea28c89d656727f592..a7d5c62ef388a876c5609a4ffa168c02272c9854 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 eef3cd90afe53d38a3330cc49892bb24932c0221..100ea5962c6d2bdd26256f57b0b52a5ea5c6e459 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<<scale1)); } // (int_cnt2 > 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<<scale1; + int tail_off2 = int_cnt2<<scale2; + if (ae == StrIntrinsicNode::UL) { + pmovzxbw(vec, Address(str2, cnt2, scale2, tail_off2)); + } else { + movdqu(vec, Address(str2, cnt2, scale2, tail_off2)); + } + pcmpestri(vec, Address(result, cnt2, scale1, tail_off1), mode); } else { // calculate index in register to avoid integer overflow (int_cnt2*2) movl(tmp, int_cnt2); addptr(tmp, cnt2); - movdqu(vec, Address(str2, tmp, Address::times_2, 0)); - pcmpestri(vec, Address(result, tmp, Address::times_2, 0), 0x0d); + if (ae == StrIntrinsicNode::UL) { + pmovzxbw(vec, Address(str2, tmp, scale2, 0)); + } else { + movdqu(vec, Address(str2, tmp, scale2, 0)); + } + pcmpestri(vec, Address(result, tmp, scale1, 0), mode); } // Need to reload strings pointers if not matched whole vector jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 - addptr(cnt2, 8); + addptr(cnt2, stride); jcc(Assembler::negative, SCAN_SUBSTR); // Fall through if found full substring @@ -6446,7 +6476,9 @@ void MacroAssembler::string_indexofC8(Register str1, Register str2, // Found result if we matched full small substring. // Compute substr offset subptr(result, str1); - shrl(result, 1); // index + if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) { + shrl(result, 1); // index + } bind(EXIT); } // string_indexofC8 @@ -6455,9 +6487,12 @@ void MacroAssembler::string_indexofC8(Register str1, Register str2, void MacroAssembler::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) { ShortBranchVerifier sbv(this); assert(UseSSE42Intrinsics, "SSE4.2 is required"); + assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); + // // int_cnt2 is length of small (< 8 chars) constant substring // or (-1) for non constant substring in which case its length @@ -6467,18 +6502,22 @@ void MacroAssembler::string_indexof(Register str1, Register str2, // if (substr.count > 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<<scale2); + movdqu(vec, Address(str2, tail_off-16)); + psrldq(vec, 16-tail_off); + } } } else { // not constant substring - cmpl(cnt2, 8); + cmpl(cnt2, stride); jccb(Assembler::aboveEqual, BIG_STRINGS); // Both strings are big enough // We can read beyond string if srt+16 does not cross page boundary @@ -6521,12 +6577,17 @@ void MacroAssembler::string_indexof(Register str1, Register str2, // Move small strings to stack to allow load 16 bytes into vec. subptr(rsp, 16); - int stk_offset = wordSize-2; + int stk_offset = wordSize-(1<<scale2); push(cnt2); bind(COPY_SUBSTR); - load_unsigned_short(result, Address(str2, cnt2, Address::times_2, -2)); - movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL) { + load_unsigned_byte(result, Address(str2, cnt2, scale2, -1)); + movb(Address(rsp, cnt2, scale2, stk_offset), result); + } else if (ae == StrIntrinsicNode::UU) { + load_unsigned_short(result, Address(str2, cnt2, scale2, -2)); + movw(Address(rsp, cnt2, scale2, stk_offset), result); + } decrement(cnt2); jccb(Assembler::notZero, COPY_SUBSTR); @@ -6535,7 +6596,7 @@ void MacroAssembler::string_indexof(Register str1, Register str2, } // non constant bind(CHECK_STR); - cmpl(cnt1, 8); + cmpl(cnt1, stride); jccb(Assembler::aboveEqual, BIG_STRINGS); // Check cross page boundary. @@ -6545,7 +6606,7 @@ void MacroAssembler::string_indexof(Register str1, Register str2, jccb(Assembler::belowEqual, BIG_STRINGS); subptr(rsp, 16); - int stk_offset = -2; + int stk_offset = -(1<<scale1); if (int_cnt2 < 0) { // not constant push(cnt2); stk_offset += wordSize; @@ -6553,8 +6614,13 @@ void MacroAssembler::string_indexof(Register str1, Register str2, movl(cnt2, cnt1); bind(COPY_STR); - load_unsigned_short(result, Address(str1, cnt2, Address::times_2, -2)); - movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); + if (ae == StrIntrinsicNode::LL) { + load_unsigned_byte(result, Address(str1, cnt2, scale1, -1)); + movb(Address(rsp, cnt2, scale1, stk_offset), result); + } else { + load_unsigned_short(result, Address(str1, cnt2, scale1, -2)); + movw(Address(rsp, cnt2, scale1, stk_offset), result); + } decrement(cnt2); jccb(Assembler::notZero, COPY_STR); @@ -6566,7 +6632,11 @@ void MacroAssembler::string_indexof(Register str1, Register str2, bind(BIG_STRINGS); // Load substring. if (int_cnt2 < 0) { // -1 - movdqu(vec, Address(str2, 0)); + if (ae == StrIntrinsicNode::UL) { + pmovzxbw(vec, Address(str2, 0)); + } else { + movdqu(vec, Address(str2, 0)); + } push(cnt2); // substr count push(str2); // substr addr push(str1); // string addr @@ -6597,37 +6667,43 @@ void MacroAssembler::string_indexof(Register str1, Register str2, bind(RELOAD_SUBSTR); movptr(str2, Address(rsp, 2*wordSize)); movl(cnt2, Address(rsp, 3*wordSize)); - movdqu(vec, Address(str2, 0)); + if (ae == StrIntrinsicNode::UL) { + pmovzxbw(vec, Address(str2, 0)); + } else { + movdqu(vec, Address(str2, 0)); + } // We came here after the beginning of the substring was // matched but the rest of it was not so we need to search // again. Start from the next element after the previous match. subptr(str1, result); // Restore counter - shrl(str1, 1); + if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) { + shrl(str1, 1); + } addl(cnt1, str1); decrementl(cnt1); // Shift to next element cmpl(cnt1, cnt2); jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring - addptr(result, 2); + addptr(result, (1<<scale1)); } // non constant // Scan string for start of substr in 16-byte vectors bind(SCAN_TO_SUBSTR); assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); - 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 addptr(result, 16); bind(ADJUST_STR); - cmpl(cnt1, 8); // Do not read beyond string + cmpl(cnt1, stride); // Do not read beyond string jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); // Back-up string to avoid reading beyond string. - lea(result, Address(result, cnt1, Address::times_2, -16)); - movl(cnt1, 8); + lea(result, Address(result, cnt1, scale1, -16)); + movl(cnt1, stride); jmpb(SCAN_TO_SUBSTR); // Found a potential substr @@ -6646,13 +6722,12 @@ void MacroAssembler::string_indexof(Register str1, Register str2, bind(FOUND_SUBSTR); // Compute start addr of substr - lea(result, Address(result, tmp, Address::times_2)); - + lea(result, Address(result, tmp, scale1)); if (int_cnt2 > 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); - cmpl(cnt2, 1); - jcc(Assembler::equal, LENGTH_DIFF_LABEL); - // Check if the strings start at the same location. - cmpptr(str1, str2); + 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); - 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; - int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); + // 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; - // Check the input args - cmpptr(ary1, ary2); - jcc(Assembler::equal, TRUE_LABEL); + // 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(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 c35daaa3d12736fd2ad5d012b5a143e933e4648b..1b0185110d770889501e0e98dd84576a17f77bbd 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); + + // 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[] arrays. - void char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, - Register limit, Register result, Register chr, - 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 be97c30acf1c9052d88d95826cc133ff1a4435d7..757c263169b77f806490c953d59cda36abe8fea0 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/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index e2047549877f9085dc5581559ff7bd8d07e39675..564ce75421a5ff302b766071b96846a74fc4ff16 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 0b17c56095ca8b4bd2e1617eba03e922a315528b..42d7823405c5f091b04f78fd0a4edeefc1af5a71 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/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp index 121ec0a02ac791eb4130acb612949e829ac1fdf9..a337ab145903e1487d6b7ecf7794d0b2536c0026 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/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 75534cf8604a4166683395fe9799814320f0e903..36c2b6fba907fca454355e13cb144c6c72c7db55 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 byte[] $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, 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 $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} + 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 %{ - __ char_arrays_equals(true, $ary1$$Register, $ary2$$Register, - $tmp3$$Register, $result$$Register, $tmp4$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister); + __ 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 1b78b73336155c205b355f5d5b55771a34139758..d63e5b68b200e4c024a2bf9e4d453417af1c03a6 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 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, 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 $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} + 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); + $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, +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); + + format %{ "Array Equals byte[] $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, 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); - //ins_cost(300); - format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} + 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 %{ - __ char_arrays_equals(true, $ary1$$Register, $ary2$$Register, - $tmp3$$Register, $result$$Register, $tmp4$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister); + __ 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 cc46781cd0a34aa3bfa803a461ae2079e660af65..00c9d7e8a94923eaf2be518901d16076c99b52bc 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 ae217a38b58cf85bc25af10b7e52cf3d465f93b5..3fbe12e94f92b1759fb9cca6cd0d144c047ca7dc 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/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 591b3c0eee6888182225a0daefbb5707c6c4bf1f..b9ce1192221d638339f05b4b1364b87a69a608e3 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<CPUFeature> features; @@ -166,11 +217,21 @@ public class AMD64 extends Architecture { private final EnumSet<Flag> flags; + private final AMD64Kind largestKind; + public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> 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<CPUFeature> 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 boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { - if (!(platformKind instanceof JavaKind)) { - return false; + 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; } + } - 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; - } + @Override + public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { + 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); } - - 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 0000000000000000000000000000000000000000..3896bea7f4f4b876e7bb5dc2e8580799e6c0398a --- /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<AMD64Kind> 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 148d2ac5ec65b0318cfc033f281de0581ad88368..10bf6a81fe722ebaf31e440035b12b065a4f74e0 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 ad26925cc359501e81534a7a337484a017e3f6b1..5dffe052997d5e9cb504cf398f8f002f1de010b3 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 e51f83ee18c7f5631e2508ee98327d374c2d4af1..409601866d65c7f1ca9abaf7c2e42a537645df42 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 a17b427c5bbdf4d5da74a6678261f10222890089..1b35f7eb37873c35f37e29335852d019566cbb0b 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 c299c8400de369f276973907eec63c18db7ade13..6161619548b60b1a884b29e0845df7dc641b4fe3 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 d0007ac08b427bd132de56ad78ae259ed77a399a..e4f3cae3beecc37c67663ec37324bce5a813991e 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); + } + + /** + * 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 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 ready-to-run code + * @throws BailoutException if the code installation failed + */ + default InstalledCode setDefaultCode(ResolvedJavaMethod method, CompilationResult compResult) { + return installCode(new CompilationRequest(method), compResult, null, null, true); + } /** - * Sets the given compilation result as the default implementation of the given method. + * Installs code based on a given compilation result. * - * @param method a method to which the executable code is begin added + * @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 - * @return a reference to the compiled and ready-to-run code or null if the code installation - * failed + * @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}. */ - InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult); + 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 bae5a53b8e7cc5f04c43dc30a57eebc9e2ca52cc..a138a30dca2eacbdf937e4006c6e0ab9d76a501d 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. - */ - 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. + * Formats a location present in a 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 0000000000000000000000000000000000000000..dabaf04f8b7786c06219e7ee92ae79b231e91193 --- /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 5cd3636eaadf1ec0d94d7e02f3c2a93db0f2c25c..9967d0cfdaea1dc393b7216fed5a982b0a6b2753 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 java.util.*; - -import jdk.vm.ci.meta.*; -import jdk.vm.ci.meta.Assumptions.*; +import static java.util.Collections.emptyList; +import static java.util.Collections.unmodifiableList; +import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString; + +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.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 d4d2881026176bf126cfa95fb0fba8f304dd72d9..295d4425ac1227376782d120c45baf79e1d1c6da 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<Data> { @@ -176,11 +179,27 @@ public final class DataSection implements Iterable<Data> { */ 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<Data> { 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 60e811f376108fab54d42236eae86bc1021f44ac..be7729fb76fa1b7840cf80d504f73f8eb3f902f9 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 fe0c84ad1dc15ff620786a845af483a9a5637ef9..815e0f0f0d4ac63de1c598dba4ceb95d16c85b44 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,31 +86,32 @@ 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; } /** - * Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise. + * @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 byte[] getCode() { - return null; + public boolean isAlive() { + return address != 0; } /** - * @return true if the code represented by this object is still valid, false otherwise (may - * happen due to deopt, etc.) + * Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise. */ - public boolean isValid() { - return address != 0; + public byte[] getCode() { + return null; } /** * 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 c11cb4df3c9462ff56d7a22e21e68c512745defc..4e0c58d720829e5450c9ed5bb24f6f74896ee684 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 b6c7e8942099c9b181677b4b93e7c4434ef0f192..8820fd5cb89fcfe2365720b499516f98667084c0 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<Register> { 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); - } - - public RegisterCategory(String name, int referenceMapOffset) { - this(name, referenceMapOffset, 0); + this(name, true); } - 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<Register> { 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<Register> { } /** - * 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 34f1100e5539840bee4b7d6fb9b6b5a32c924c8b..b8c150756271e2f08e3f6e48207cc704e337e28d 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 57298738551ff863846243a9bbf0835bcef3bf35..f942b723dbca0a9b9f58274ce1258c0d31c9f9a4 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 4fe15605776227b41eee002cf4dbb2e61f1faf93..86b9257965459005c412fde61ff14fbb2765bc03 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 b578228ee73a6979ee3aba18d4a3e8d5b446aaae..7cea61b4e0ae1b6aebff7b0fc8ca31fb0a6290bc 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 1fa157a77940678a09f4e0f0fa1dd1a2e5dcb9f0..efd65fa4921ec5cc7bc9b70d2c34083d77510fd9 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 725650ef152b42aea2b180ea310ce7c324855cc7..4460b5c350ed9e131f1ec970ffefafc744733c96 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 edf6f45a360e927ba1890438ade3240b5d5dcc67..3ddde182b01c34238e8925021133fd8b3f806b71 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 d6da8b8851413dcfbe760a94e8cdad7e5162f557..edd26878d25c91c7a5083814ace11e9a7c71d373 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 <a @@ -78,10 +79,12 @@ public class TargetDescription { this.arch = arch; this.isMP = isMP; this.wordSize = arch.getWordSize(); - this.wordKind = JavaKind.fromWordSize(wordSize); + this.wordJavaKind = JavaKind.fromWordSize(wordSize); this.stackAlignment = stackAlignment; this.implicitNullCheckLimit = implicitNullCheckLimit; this.inlineObjects = inlineObjects; + + assert arch.getPlatformKind(wordJavaKind).equals(arch.getWordKind()); } @Override @@ -101,7 +104,7 @@ public class TargetDescription { this.inlineObjects == that.inlineObjects && this.isMP == that.isMP && this.stackAlignment == that.stackAlignment && - this.wordKind.equals(that.wordKind) && + this.wordJavaKind.equals(that.wordJavaKind) && this.wordSize == that.wordSize && this.arch.equals(that.arch)) { return true; @@ -116,10 +119,6 @@ public class TargetDescription { return identityHashCodeString(this); } - public int getSizeInBytes(PlatformKind kind) { - return kind.getSizeInBytes(); - } - public LIRKind getLIRKind(JavaKind javaKind) { PlatformKind platformKind = arch.getPlatformKind(javaKind); if (javaKind.isObject()) { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/UnsignedMath.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/UnsignedMath.java deleted file mode 100644 index 3e688528288ab83fd9f4b34f81c56913fad87f28..0000000000000000000000000000000000000000 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/UnsignedMath.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2011, 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.code; - -import java.math.*; - -//JaCoCo Exclude - -/** - * Utilities for unsigned comparisons. All methods have correct, but slow, standard Java - * implementations so that they can be used with compilers not supporting the intrinsics. - */ -public class UnsignedMath { - - private static final long MASK = 0xffffffffL; - - /** - * Unsigned comparison aboveThan for two numbers. - */ - public static boolean aboveThan(int a, int b) { - return (a & MASK) > (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 982617d46bbd0465075268c8e434bee00781bf03..20bde745829ad91a9abf0942233399b63f62efff 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 047d84b385051c232f199dcc94d685421a22b4be..7b4b2e60af741f9fd6072d9985e2be0e3311755d 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 14d2659bfbc0c6e49c470d0597ff217a2910e77c..0000000000000000000000000000000000000000 --- 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 1010108f3ee807255c5663d1ed4083123d29a4d9..63f1ea5df745bf5b51bcc45574fa9527a57c80a4 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 318e133133e1b0220956fa51985c01e3c002aeea..7453b69fd9285aabff651fef4e3f3be7e1c2422c 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 99f7e4fe59dd72dae19027626544a4c67eec6e5b..3c48c1dc77f3546c1ffd03105a1dac012b3b82b1 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 3c53a309a9f0b45f301038dc3ce62fb9a79fefbb..485d2c65a3aa4b4c6f5ed067d6917582ef20e178 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 8b07d6747ef4f0976f114af048fc2a274e0cb59c..0000000000000000000000000000000000000000 --- 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<String> PrintFilter = new OptionValue<>(null); - @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintCompilation = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintBailout = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true); - @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> 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 54138bb92e14bd8d73074c6d5bb7e162a5a96777..d5d31ea86e5805fb4f9032f40037a68f05bd1c31 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 java.util.*; - -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 static jdk.vm.ci.inittimer.InitTimer.timer; + +import java.util.EnumSet; + +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 6804a5eaa61283ce93fdc54e2c36f6338ad63cad..876263c75ef585412ba7e27a84acfcdc9efa7ecb 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 java.util.*; - -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 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.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +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<Register> 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 0f26eb6ca2299543231e25ba2b3b16d089ade2e3..d9339c2fa7e634f43ccc53374a65f05ae9d73fd4 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 cb47b2ea564d14e8c4930eba37990eb2a1ff017b..58dfcdc3e556cd4a65ef348ecc43abb497e61d49 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 java.util.*; - -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 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.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; + +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<Register> 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 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 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(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<Register> 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 1e96b96d7c12b16669b763393e5f53ff8a2fcc30..536c93af36eb521176abd76296cfc2d29f2683fd 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 <code>bytes</code> is <code>null</code>. + * @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 b1ccd16d14d29861f429767bbb75b13e1d3fc01b..6f9770a5c2dce08c54eec5baa58aee756f5344a0 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); + 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) { + if (method == null) { + // Must be a stub + resultInstalledCode = new HotSpotRuntimeStub(compResult.getName()); } else { - msg = String.format("Code installation failed: %s", resultDesc); + resultInstalledCode = new HotSpotNmethod(method, compResult.getName(), isDefault); } - 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())); + } else { + resultInstalledCode = installedCode; } - 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())); + 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); } - InstalledCode installedCode = predefinedInstalledCode; - if (installedCode == null) { - HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false); - installedCode = code; + 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); + } } - HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult); - return installCode(compResult, compiledCode, installedCode, log); - } - - @Override - public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) { - HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; - return installMethod(hotspotMethod, compResult, 0L, true); + return logOrDump(resultInstalledCode, compResult); } - 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 0000000000000000000000000000000000000000..dee71da6167400f988c8603c300a9033b4dd9131 --- /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 c70c46f2fbf8a5fe7add599718b83aa02741e399..a2ec65fbafc0f9ae0536523a637ead53575391b3 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 b23aec07823448b0140096f3b484c5dbe4c88be0..e81f35b5e43cf34093d5546968b9905338898d3d 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 228848c997f06c7dc401c7eedafc578a43c04c5e..7243305606d50279ddd13b2d0dd6c522ba1c2c9e 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 55544367808536a006a95b530715ebc04d8abba7..ee4cb7bb397d02ed5db481e9b4900617017e27ed 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 cae64abaa8dfd16a3c3ca8bcfacd9c27661db86d..0885a2dcded9c6e5d4c74b1932a86061b487c91d 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 843176bae3d4b0b2d805c8859a54f01dc3d7d9be..a5d165feb61fb1a28f86d36ab157f8217254834a 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 java.lang.reflect.*; - -import jdk.vm.ci.meta.*; -import jdk.vm.ci.options.*; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; + +import java.lang.reflect.Array; + +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 00277ecd3f43a31f0309f086d6a23fddc3e07024..aa8368d9777091f950f62f7a758795607ce00bac 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 50c51da78e9675b25406e6255ecdd86ead37ec2f..1103fb73d98fe187824cf1944634ac8472ecd9ca 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 1a0e54231659b6c0e6b6c169bbc15b58a5acae4c..1e242413b6323832988af4d7ca8ffe44f93e793e 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 "<none>"; } - 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 b3bad532f7ffa09f771a7beec9d83c784795f4dd..59299ea85166733709a65f62f2fd6f922947a71f 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 jdk.vm.ci.meta.*; +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.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 6b5204f51612f1dd70b581433b6c0b9cd87bddb9..7ea4ebf407d1d9c9c6108039f5e05aa823e833bf 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 java.util.*; - -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 static jdk.vm.ci.inittimer.InitTimer.timer; + +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.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.<clinit>")) { - try (InitTimer t = timer("StartupEventListener.beforeJVMCIStartup")) { - for (StartupEventListener l : Services.load(StartupEventListener.class)) { - l.beforeJVMCIStartup(); - } - } - - try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) { - instance = new HotSpotJVMCIRuntime(); - } - - try (InitTimer t = timer("HotSpotJVMCIRuntime.completeInitialization")) { - instance.completeInitialization(); - } + try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) { + 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<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>(); private final Iterable<HotSpotVMEventListener> vmEventListeners; + @SuppressWarnings("unused") private final String[] trivialPrefixes; + @SuppressWarnings("try") private HotSpotJVMCIRuntime() { compilerToVm = new CompilerToVM(); + try (InitTimer t = timer("HotSpotVMConfig<init>")) { 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<Class<? extends Architecture>, JVMCIBackend> getBackends() { + public Map<Class<? extends Architecture>, 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<String, Field> 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 13665ac0f5684b4066d922939b81b44184b9ff20..12cc5255eadf6b5f4d163407f21e98047cd5c915 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 8c1a9808d7e2f5690fda03edbea7a8d2f34c2f4a..ef8253596d8af6971386e34284dc9eb7842718b5 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 ed48d9b34f411f745b7fc16b664b1d1b3e5f3c56..a352bb4d842ea396b18ba28d23dcd5a85d753aa1 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 40efe0319c5a076aa7c1d64e031ea12adbc2fa53..953f00f98848cfbbdd28550fe9823e4a97107435 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 e3fb69d8b80eeed99154a1e42a169a3ba0558fe0..5bd116cd57b6e98f2bbf4a1f1c15e105578fd9fc 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 fd40b38a7e8cbca6f307e05c5d328c8226b2c170..95a9670f311115b141a03225265647f2d4afd3d1 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 d37328eb269c053deff81f67e8cb791281a26998..a19aa486e2cd1a6d1bf3c8a2399d57338b51b5fe 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 35e4519c4c18ecb3ab37114c1219cb1118ab73e9..43051ab5e2ac57362bd106a4d20f4f066bfd3c17 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 c6e8e72869e8db135c3e75d0a3210e2c6ce401a6..3fa045a618e0088923882eda3f251cc5c91235a2 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 8fed389a799e8f0d6d812225ed6b666d9eff6be9..1741a080720571aea7520e3892987b29c103a0a1 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 7f5ceacd9868d266ffc0752fda24971ea2959b58..7ac97ebb59fded22707e184f5261fe2a59af15f3 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 40c1d67a869a8b98a7c3fe89f6ac495f3e4db769..87cf467f6d77fbdd259f3f6178bb96dfc70b90fe 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 134e69c28bbc57274af6866795392ff7e56b54ef..b859c124a4dfad24e1fecaf2c992b913b955ab6b 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 83219dec4b740f27e0045fd6e3e2a884a4611d5e..f8aa3cb9310bb905344f98f32f73896c59fd7a37 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 6edf5ac3339536a08fad7bf81ada6e753c410e2d..408f7268260d38e3147f075fb403b88ac3b7e9d1 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 e3c7cb32da94bbba7b53bd29a6da304cf3f8451a..0dd51105445a4b0748b55f27a29c2d6b6f07ab80 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 bedd564694c41b33297bc6c7b64b99e48e8982b9..06f2983c6457a3980cb66e04cc553a31340ab351 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 7da7d4e042d4516f2f3053e13f80ac9f6d5175fd..020343e164cb4f7d5c70f781c3548cb1a1963e6f 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 a35585a0d6c7f767ccbc08a5d1fd9d1928d56f29..5bb7c66cf45764eb2f8e3bb4c648254698c48b15 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 aba4598b016dcf4fdb6bac0125afcea31663b3cc..00b0c0de8c9e895924ed850c5f4c0bc3251dd399 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 4535cefce85e69d0ba8837771eb16f51c838b502..cd89be3e5630e2c65942b7634b1f8471c461aa68 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; + } + + public boolean isDefaultStable() { + assert this.isStable(); + if (isSyntheticEnumSwitchMap()) { return true; } return false; } - private boolean isSyntheticImplicitStableField() { - assert this.isSynthetic(); - if (isStatic() && isArray()) { + 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 2f91cbe59dc09b9241b38fa86169c0ed0ff0480a..d1ecdac098db35bf4dd6b3e1f812a9017245f3c4 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<Boolean> 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 7e931f370eed5a4cd26047dd638e5fb90d7d3a5b..4b7184e05292fd14ecf6471221e7dde4b7477d3a 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 jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.options.*; +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.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<Boolean> 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 extends Annotation> T getAnnotation(Class<T> 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() { - if (toJavaCache != null) { - return (Method) toJavaCache; - } - try { - Method result = holder.mirror().getDeclaredMethod(name, signatureToTypes()); - toJavaCache = result; - return result; - } catch (NoSuchMethodException | NoClassDefFoundError e) { - return null; - } - } - - private Constructor<?> toJavaConstructor() { + private Executable toJava() { if (toJavaCache != null) { - return (Constructor<?>) toJavaCache; + return 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 365ff70b11ef06b92c8a70fa19673fb370d0dc44..cba1ee3154bf54e47afd3e43c109961d60d50376 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 18c04ece6bcee8d04cae844423e895e5d33306cc..3501387061b73b1b79c0ddd5d31b75a4952ea420 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 735ff43f4eb4f9de11d416454095ae4f03b906a2..4ef227ec823442f004a062b4503f7d30b2db3491 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 jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.meta.Assumptions.*; +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.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<ResolvedJavaType> 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<Boolean> 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 7d0491553f97110e01737739ed92bcbb7a0a288b..7a8f3e8a63351b0c1ae4aaa9b931e93f57f88faa 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 0000000000000000000000000000000000000000..5ec69e5819ab65bc72e407325fa79507170506d2 --- /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 0ce340d12ac1e20b7f4edad76f1952d4467ab98a..76cd07a39795b22689376a24b8e324299a776377 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 5d873e9ac95c7081f0466c008b07d685f0d8c2f8..c6ad02a311fb40e32c0ce77f13769cabe0821125 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 0f9c7a05ac3a5f47635e852f25c98161a64be2cd..e619fb45ee765dca3830bb52762e08433d57515f 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<SpeculationReason> failedSpeculations; + + /** Strong references to all reasons embededded in the current nmethod. */ + private volatile Collection<SpeculationReason> speculations; + + @Override + 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(Object reason) { - addSpeculation(reason); + 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 5ece48ac8dce90fc950017ba8d2b8a2471e64b3b..b40ba20ac4d4ea00f3e40e2f756469cb762be733 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 0000000000000000000000000000000000000000..9a7751d6fadac78a40f55d972d0230ad063da6ac --- /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> T iterateFrames(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip, InspectedFrameVisitor<T> 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 45fd7b9df44053c2f7b72169b17d8ab97b125cbe..d1ef070e39d8baae8cb85f0c1384087cdcb94ed6 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 1e945d48de1ed30654d2a4060205910f23a0957e..d9e3390df3af6f47703b7ee48df4a84c9da5b927 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 f5cbf2f6de1aeba450c43de50c46f1c90a0dc925..384b0f845946767a9bb31535d8c89a1269d6edf4 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 sun.misc.*; -import jdk.vm.ci.common.*; -import jdk.vm.ci.hotspotvmconfig.*; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Iterator; + +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; @@ -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 3a449db38b03e1cf8cb8a4faba67878dacbbe4f5..5f82244d055860379a058f378e5f7957b4fb0bc6 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 java.io.*; -import java.lang.reflect.*; -import java.util.*; - -import jdk.internal.org.objectweb.asm.*; +import static java.lang.String.format; + +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.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 520a3da4cc97fab13625ad4621f7536c0f2411a4..c9d3db7ef09be2eef55459657d260239b8365747 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 8c06c321aced8b91a0faaf6caf0a47e729b8d6bb..0e1398eeaea441236063f9df58f7d0142e7bd4de 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 d1df11f0eb10c3960245c416aa5d8b2d205d992e..444b25bed3d87b305a3a4c8982f398c0003edf3f 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 2cda0c24241c4f65d999970c808529cfe13bf4b2..e386dc0ca77e91f74681ab7d56711c2a1b2d4a5f 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 9e5df8268dbe25ef57667ac52a41b7b470d8073e..8e39f7191f1bd86ad08d7fc877f353ee4e43ca6e 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 4e810f9bedde2af5b2e6462642df0217d33af0bf..0900bfa207dab7f28764f257cca633eb77b88125 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 bf8a465f52f0f2a4dcd0c9d89c934ecd8a8ed360..10da8b6ecdda2cb3714b9fc4006ac47fa4dc7859 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 7cf45a51c0fd1d1e0aaecade66b0352784fd71dd..f993fd620eefc5f0bda7dd9209f7396bd0550fa5 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 158a6879309566737832ba05accee5871ccf14bf..c58c9e72fd50c7ba9ff7b1f3aaad030bd589f5b4 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 d8b5d3e13deb617b7c86af36043739182ca07733..99e9ac39fb286eacfb7320cf838b0b5b07fbe5d1 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 7aed441a2d6af4cbcc5684711a27e0175d27c7bb..91ddf9508797170dcbe0ad0f86709d7ee1dd5902 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 4e22c3948da016b988e4888e464caac124c5a2a8..1be06f15630f2b7651a55cfe9135e263a14b956d 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 f90e9fa33ffcb6dbf6a4261ade8fd58965e73e1f..dbbc950d6b2e7bc1f3d17979e6a2f35e4d463839 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 6e130abb4460e88af54b9e8ed798f3837142ccdf..1db2b98c7eab2917b11c322d6e8a93afab6a2371 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 f5a9979a4ba622eaa7ca9827ec628fadf3e0f0b0..3157d3cac1408e6e6bfeb6005ed24fdb64c0a8b4 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 8b03551ee8bfcf319993f0fee8b07288464827e1..4beae9daa05451f5b2404d6c28cfbfdf662507ff 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 6af1dac11c5ee909117c1f7b90a76b17c3aac411..f44c061f764b8c7d2717b308eec83726c877c189 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 dcf965c03a0fec1c3e0ad2f59b21fa70929cbfb8..73ab3f5680cae481aa1e110d1aff888aec9a9ead 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 2b2139097a491b9b49c51b945e491c38a695e86a..bd8df8299c2aa9e8380b7627ab21fd0913d438c2 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<JavaKind> 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 8244a1701d0cff55cf35bae692096c821e47c15a..da61e58b027ec45a2503d953102bd793148c4c27 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 afa6ee3c7d2289da7b30d42c0c315057064a5eda..f63c6f5a6d3c26940e8e18b833f2c7def76d45c4 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 4e3b20f69b0b164faa72b11b2d3ff93abd400e7c..9f5ff78f0a38db1747a591f1b4bb4bc202d1b385 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 e76f70935d62e4614c69b612eff146eeea6d4989..bafb822c86da03fabdf42d08783d284f4237f7ec 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 9840aaa53679372307589a3f290040abb45dcc5d..220c17555c6059c471103b93dc5f041190272e9b 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<IllegalKind> 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 68a652655ca3dfed5eede3d9ca11a65e5a8ffc74..7cafe042a2a350910d22a23cc1bf4707ac108391 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 3715ab4994e441a008a79a8a74b9eace640610f0..b63b3dc740a4c6cf54fe7fdef1b13e83a9c70506 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 1c54ec5c5eaf45b06bbd9812f50c61bac731bf98..5bc8f20a4379a68cc879caa07906cf2297ac6f7f 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 7bc325087af7e5c120575a5ed2fc82159e180fa7..c2df8929fbe36c4b8090b6b7dfaf5fe6eeac5f16 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 e4de0de87c8392ae4c4cb11606a9c4a461187951..8397fef5f08309d37661143198c6d86babfdfbe0 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 f6c20bba1a4d525c06ccdfc2d28f64597d1a4166..2f28c7e31f33358e95626c161e48b8bbd8f57261 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 java.lang.reflect.*; +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.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 e1deacac1438cd00df7d438963949ed537e4e279..6947c9aefea7d40adfda021109207c7159572daa 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 bf599debc7ef19248f2aa25eaa022990e3c46dc8..135b667e90c762e3da288ae3e497b088d90d127c 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 7a695f083a5c6dd4920fdd808adbbfdb5e06d7f9..b1eb007c0654c57d6b7dbe8ab9de33810ffdfbf7 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 9e516534d16b74676fbfd41a3afb23b8bc727ca3..326a24bd29e4841f4822ddb2f4258844445a47b8 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 1f2bdf3e329ea985b54e12962e8dc0c9c9763475..d46a0fc3dce07c1e0ca30e65585d4ea8a36f5750 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 3c63b25298d4f2852c57ff2458e7621cc949e995..05231627c5ace099c5f0c1e0b43cd76a58220069 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 57ed095a363a9568da2d106220ad6631861e01e5..4330e65715e7286c5c5c27f19b1236748039f933 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<Object> speculations; - private Set<Object> 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 28153496314c15dba1eb11cea4d03678a32a9281..95422c241351918f2cdabfb97ffd08adb1e6401c 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 javax.annotation.processing.*; -import javax.lang.model.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.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.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<? extends TypeMirror> 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 267692a1c07d179c4ea3f47f553ba5457ee415fe..e6149955c77b25b05e911283301a37b597c1da5f 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 a3603a4323aa8bde30cd1908a9e3547131315830..0000000000000000000000000000000000000000 --- 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 - * <jre>/lib/jvmci/*.jar}. - */ -class JVMCIJarsOptionDescriptorsProvider implements OptionDescriptorsProvider { - - static final String OptionDescriptorsServiceFile = "META-INF/services/" + OptionDescriptors.class.getName(); - - private final Iterator<File> jars; - private final List<OptionDescriptors> optionsDescriptorsList; - - JVMCIJarsOptionDescriptorsProvider() { - List<File> jarsList = findJVMCIJars(); - this.jars = jarsList.iterator(); - this.optionsDescriptorsList = new ArrayList<>(jarsList.size() * 3); - } - - /** - * Finds the list of JVMCI jars. - */ - private static List<File> findJVMCIJars() { - File javaHome = new File(System.getProperty("java.home")); - File lib = new File(javaHome, "lib"); - File jvmci = new File(lib, "jvmci"); - - List<File> 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 ffbaf4d0bd62e7e18e2b9fb763101b7912f6a6cd..804603814f12175b9142c43e9fa62d9b26c12b25 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 5a9f920a198cfc22bd6cbb9c20079472d881103b..3e0537335d399f451c2f2c64d7b9757f551b9e15 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 343edb1d1139ca5c7511f59cc8f981cfc7633040..6abcc91d936b8e6e620e3eb6b22ca79ce079bb8f 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 62cb9c80831dac58632072a15c02d8c8eefedf12..a01a05d040e6acc1d461830f125286e9282b02cc 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 59893978ae005a6cfda8ce289f3d50c82c092913..0b8a6411181e07530f8eda795dcc26dc33fad473 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<Boolean> PrintFlags = new OptionValue<>(false); + private static final OptionValue<Boolean> ShowFlags = new OptionValue<>(false); /** * A service for looking up {@link OptionDescriptor}s. @@ -54,7 +66,7 @@ public class OptionsParser { } /** - * Parses the options in {@code <jre>/lib/jvmci/options} if {@code parseOptionsFile == true} and + * Parses the options in {@code <jdk>/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 <jre>/lib/jvmci/options} + * {@code <jdk>/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<String> 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 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<String, OptionDescriptor> 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<String> 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); } } } - return Boolean.TRUE; } /** - * Parses a given option setting. + * 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<String> 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 <name>=<value>} - * @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<String> dst) { int eqIndex = optionSetting.indexOf('='); if (eqIndex == -1) { throw new InternalError("Option setting has does not match the pattern <name>=<value>: " + 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<String, OptionDescriptor> resolveOptions(SortedMap<String, OptionDescriptor> 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<String, OptionDescriptor> 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<String, OptionDescriptor> 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<OptionDescriptor> matches = fuzzyMatch(options, name); + List<OptionDescriptor> 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<String, OptionDescriptor> sortedOptions, String prefix, PrintStream out) { + private static void printFlags(SortedMap<String, OptionDescriptor> sortedOptions, String prefix, PrintStream out, Set<String> explicitlyAssigned) { out.println("[List of " + prefix + " options]"); for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) { e.getKey(); OptionDescriptor desc = e.getValue(); Object value = desc.getOptionValue().getValue(); List<String> 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 886702a548536254da38aba600a3d8d369f46195..3b4f073dc87fcd3198907954d746c562854f9421 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 98b02cf4cca5547e2518b942e7392d3fcd0aa50c..28b296e095b135b022d03369c16509d49bac5bc8 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.code/src/jdk/vm/ci/code/StackSlotValue.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompiler.java similarity index 68% rename from hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlotValue.java rename to hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompiler.java index eaa71c5f36748d341bcc7d742506a560004183bd..72a1b53b8f9f8a58fa41ab8e447648dbecce94ac 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlotValue.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 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 @@ -20,18 +20,16 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.vm.ci.code; +package jdk.vm.ci.runtime; -import jdk.vm.ci.meta.*; +import jdk.vm.ci.code.CompilationRequest; -/** - * Common base class for {@linkplain StackSlot real} and {@linkplain VirtualStackSlot virtual} stack - * slots. - */ -public abstract class StackSlotValue extends AllocatableValue { - - public StackSlotValue(LIRKind lirKind) { - super(lirKind); - } +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 98e08dc0e82a6c386326303528513b2baa1dfa3f..7bb1f592224e35178654f0ed829bd56ec28daa4e 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 960a1d62e53021f41c973d2ba91663a905ac353c..b705417e941dbdd2fa91225d36d382a70d134002 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 4b027c3c0bb29e83b911c799c2efb64f2f1b82ba..d8aea46725746e16911d7f120dbbd1b01eaa0d99 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 javax.annotation.processing.*; -import javax.lang.model.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.HashSet; +import java.util.Set; + +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 4ae5b12b06a378013b87e343e1638a58b25013b4..003d8f7dcb5f764db6dfc2ba1667f84912567ccf 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 @@ <module name="NoWhitespaceAfter"> <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/> </module> + <module name="AvoidStarImport"> + <property name="allowClassImports" value="false"/> + <property name="allowStaticMemberImports" value="false"/> + </module> <module name="NoWhitespaceBefore"> <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/> </module> 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 0263d5afd59b790c8906499ac59e3cbcb1b7df0d..4d8a7f9692b2135a9fde07e2ecaaa76786448408 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 6b574badf249315db6e4c4424ec4ca35c548ff4f..9a6263a9b9931ff4310718ecc00a967755d84d67 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 a68c68e6adb7a8691ed1ba6ed000097921fa71a8..7f99e331e1bedc5f3362dfea2f14632e1d4d2f0d 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 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 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 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 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 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 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 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); - - 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 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 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); + // 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(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(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(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<CPUFeature> features; public SPARC(Set<CPUFeature> 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<CPUFeature> 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 0000000000000000000000000000000000000000..0e2fcae46b534c7305ba32cbd11726d6559be0c2 --- /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<SPARCKind> 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/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index fb3ea6484146042c6ea051ea38c3e3109b5dd182..0f21ec44f03bfda5fd205db9ae83facfc608a5ea 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -3811,7 +3811,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); } diff --git a/hotspot/src/os/bsd/dtrace/libjvm_db.c b/hotspot/src/os/bsd/dtrace/libjvm_db.c index 87a9afe24ffb0494a03241c1b611a542e0fd4ebb..7a7105c1b2550a36d7ff9461d492d3c6f1b762fc 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/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index cce3906e0c9b2297a937a951fb01b974ef6078a0..9c221c630612ed3672ddda52943f77b42428cfef 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__ @@ -3745,7 +3757,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); } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 05d1850d52eaeac7d03db2357020185ae4a3af4c..e09ce3c466a99323986faf8d68d209ad1d9335a4 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2794,7 +2794,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) @@ -4187,8 +4187,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) { @@ -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 @@ -4960,7 +4960,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); } diff --git a/hotspot/src/os/solaris/dtrace/libjvm_db.c b/hotspot/src/os/solaris/dtrace/libjvm_db.c index 6bad77b68bbf0d744f6ad85cebcbe19f09c289cb..e00284532a6b96f8a2410e28a66c6f946297049f 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/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 2f5172da6b8f1e84911dd176170f652edc6e9fab..6d7f62d83bd6910993397625f7ce2493fc90c36c 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -3774,7 +3774,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); } diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp index 3456414f048540102ba98b5fb1ab39d1f385fdca..4ececaf1cebee950e858ebf9f917d7685c9dcd38 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_cpu/linux_x86/vm/copy_linux_x86.inline.hpp b/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp index 175019b8644f1cc056c9c633251c907a066d482b..c35f85524ca2a405c98d34139bf31463407e932c 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/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index d63732be3802c71c4e3b9237a5f2a41c3beb9fba..f17330ace6547f15a896709a336aff374639a9f1 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 79a65f1683379d8fe9c99e45b61ec575302a7cc9..82ba5f9e2d71f1f2265dbf0a483da1a5bcaed5c4 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 ef0a71fef254e99c3b40b95d450afa49fe6d9abc..7453d38d61be536eaa2310b58c2067730f15b93f 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 1ab5a5d6d8dffb039572f87f8391dc5c43bd9213..9febe786a35b609a408a2baed2859d35bd810d9b 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<oop>* oops, Klass* k) { } } -void CodeBuffer::finalize_oop_references(methodHandle mh) { +void CodeBuffer::finalize_oop_references(const methodHandle& mh) { No_Safepoint_Verifier nsv; GrowableArray<oop> oops; diff --git a/hotspot/src/share/vm/asm/codeBuffer.hpp b/hotspot/src/share/vm/asm/codeBuffer.hpp index 50b699c5e3e559466e78a651999dbe9f5423bd3d..387a5b7cced77eb676eb2b1f8235d02eacd6e9c7 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 26cee689ab0f3c2ffb46f78a0a2f68ee6ec3f1cd..e4976f18bc630f8260f0bd908635db3f4463a258 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 8377dbcb56c83cdf9bcc8db8976647548d37ac49..5dbe6c209f3298e3fa6280fa337aa20697359cdf 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 5ac2ade31fc5bfa4baba89d7cc2ef62b9fef0c14..fb3f1877eb67be1ad58ac4bd876e1e61e7b01aae 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 5b27aae2a058fccaf556fe9c0edcf4d5b5fd3c47..6513fe1ab336bbd43de36dfed74d1432ff3778b5 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 40af90bc13d7dda17b82f41be7c5efcef0231c98..4fb1e184d6d59cc14adae44c87b97c3c4ae535fb 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 b61786c58c56daf0268169579d00d0fee23dea53..8f6bf233f3dd776cf2f0af1ee55758fff803ebf8 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 d5a3f947b599cc70c91d268aa64f1ce3ac7d1b8c..e8bc40eba933ef6cf074ed1b99697cd3d73a8ef7 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 f188dfb942d02260c2e05b82cf772558924ee907..a45d221f740a253e766c441539e243ca02b2f0c4 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 f0f7d3463a807704892de1475ae75ff7af98102b..69956e7d9e0edb1fbbb630d3e302c93715204d2d 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 7d2d19774c067c1602a39f0ab96787d8141ead10..ebff3a90d902011de442ef677c98becc99c1e740 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 4e1d2e99bd1b500f89d0a4b09df049aecf4c9b2e..9c9d7b300c24fe5eaa793411e5378676fe4eb195 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 f50a502db0ba64bb839099c6a74edb74952e3910..b1a95bd38f643ca86056ec0abfa0d010714e427d 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 cfbc7b8c65fa0ebf0f0964a92c5c3d96ba1e7d0e..8ed8fcef21135cce518e67d93ddf743b93d2c837 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 080acd380e11a1eb914a06d2541514b28695bb62..b0d3234af6e1080991819f354aed83deac680118 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 3014c7f4a0bf4168cf2532537a768f0a33524e0c..0acf602a4cc218f422f2e295a5feac554a90e058 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 2b035c2af0fb94f2f05ce9321d5d147ec4ac40b4..d1946659fb76933ec536c709909aac8bc061cea4 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 295b7c9282eab84af03fcfb8236dcfbae40b4749..240ed839bf0afa63053d0797f273884372d2b297 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 3e22b50d2c408ba3838aa2c07c18b36337ad9693..27a5c1c8c1647bf773dbffab92c3efac7ab603b1 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 634ca47981c891c49ae2e4fd63ca5906f4cf8383..79f80d2bf81e4ce99ef32334536bcd748051745f 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 1d0f067c3bcc3dd7c065780fc5f2bfc42612dfe3..37ffdf123042612ce7f31a94d67ec8d8a35febb7 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 43df753cb49830ae54d5c04a2bc7ca11d5512ae8..32ba363ac6d10b83c56343bbb7e1d9941df796b1 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 15113348e217c86f0fa70eec67596dee03319f3d..f85379fdb439570e21e93519457be8d1b1066352 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 80a767d91eeeb6506b89964859cf8632b943ea00..ca4c99995b4ab169af2850b67f6990e1fc30be65 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 991fc2831279120154190897662d9136e5950ddd..4b1e4ba603b0e1ff35cdf577ffe586dea88e3a98 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 74301472a6308bcf079efc05971281cd4ddf1c31..01e338e0b55061815f5a6a5fc4fefb5ed512dfb0 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 3e1f13de4ea0690625b67ac5a5c7c1d19a7b9279..2d0479eae9c950c1fd6c711eb352657aa51b44cc 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -315,6 +315,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 +328,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 +648,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 +824,7 @@ Array<Klass*>* 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; @@ -3175,8 +3177,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 +3214,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 +3379,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 +3458,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 +3592,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 +4114,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 +4318,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 +4333,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<Klass*>* local_interfaces = this_klass->local_interfaces(); @@ -4338,8 +4341,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 +4413,7 @@ ClassFileParser::~ClassFileParser() { void ClassFileParser::print_field_layout(Symbol* name, Array<u2>* fields, - constantPoolHandle cp, + const constantPoolHandle& cp, int instance_size, int instance_fields_start, int instance_fields_end, @@ -4687,7 +4689,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 +4709,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; } diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index 10d331fa64106a571ff062c7af47768caf12a66d..fc9b7a0c1791e7247304a129cf7b25bb09c01b00 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<u2>* 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 d1ff1c3cbab86cfede5419f544aa0d284b4e610c..3d0727ed67e7e14c96c5f7bb8c83514f55eb72eb 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 0026d88ec8880f5d2e6d8fd79eb2a731ebc4f35d..39dd55f9a1720d01849ca76a0f2f544452cf7604 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/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index 3621af33f83ddf80a927421182a28a62ed499c93..82e4e71cf813a544a3b998cb5a52ebb670191b25 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<Klass*, mtClass>::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 7ce8d34e5f573abc0ea994acb210a239f8308bb7..1f6b568670e341d6b31efdd524bf778164710ccb 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<Klass*, mtClass> { 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 fcdb0e0c6e54bb735af02f961c5738d631d427a5..a9f7c4616c64da3f30267f013591f5545809ddb5 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); + 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) { - UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length); + 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); + 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) { - UTF8::convert_to_unicode((char*)symbol->bytes(), value(h_obj())->char_at_addr(0), length); + 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 4199d350bee04158d0767a3980feced4be43f296..403e33e9ee3bad73febc53d2e7dd33adc2f8ae85 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() { + static bool has_hash_field() { assert(initialized, "Must be initialized"); - return (offset_offset > 0); + return (hash_offset > 0); } - - static bool has_count_field() { + static bool has_coder_field() { assert(initialized, "Must be initialized"); - return (count_offset > 0); + return (coder_offset > 0); } - static bool has_hash_field() { - assert(initialized, "Must be initialized"); - return (hash_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 <typename T> 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 1cdc34d054857e647d9985cdd6827e95f2b33bf7..5780bad832ec1fc2801d428a4f01b23e952c5d38 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 10d7650db58756eca939148d27724a6d6d5073ac..22f1ad861f041bc68beaa9afaded9ba8da4bad53 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 ca0d85af0fbeba0569ecf90c0d2a33d8bb95d50f..f5fc9b40845029522a137face54bb3e04e7872e7 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<Symbol*, mtClass> { } 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 cef42b1888d0621e68b7ca6ae5c87c5bb38af993..d2e11743c2e344417770305acb49fe2e32677d92 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 c9e76827cb4d74fd7c6fcf221edda80875ad2e66..866a4b122a3f52d22335d104856a75977e440508 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 c14cd9e036aea56bf04397f6744445c2b4f79209..7298d8480971df580cbe27378a7ddd584dd5fcfb 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<oop, char> StringTable::_shared_table; // Pick hashing algorithm -unsigned int StringTable::hash_string(const jchar* s, int len) { +template<typename T> +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<jchar>(const jchar* s, int len); +template unsigned int StringTable::hash_string<jbyte>(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 e5b9e2b6cfce8b9d892db88ce8fba92d21dc4ccb..f7dc5967dfcac25b79a86aebfcfb28a1a6f1cb47 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<typename T> 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 b5c3a157e12d3afe0050a293d368e867855e7f82..eeb23890265ade8d0d7934b9747ac00dbc7fb7e4 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 4095e6e7615958714553a3155906114b61ce5943..29ee8d2b77904c3da91da03a15b5f7d71ab8151c 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 bfae05db988762353a12157301a978bcb16bf7b6..ec6340707679b55ef36f9222d904af5c67a18975 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 4eb39c59e9b5aacc6bb12806dd6d9c075cab8b89..b9491903cfd7ffdc055642a5859085377ca22cf5 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 2b4e8452b02bc4b0b52f934305cee2c168172f4d..d1537011db89af8fa2e39cc8cdd2f00e201af484 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(); @@ -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 c9aa6d50789d2c55673dc4b4457e491827d9f071..e265355e733aa41803e0d053597d6f73c48c5f86 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 9dbdb53a4d30ff351f056b588004a9b2e311318b..bfb99c67630a706ea5e908a7ef38a759a7905f66 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 a08a397506bd5083fe3c1b818798405523065aea..f98f400064dfbd198f87248b1e15a7193504d4e5 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(_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(_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;" ) \ + 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) \ \ - /* (2) Bytecode intrinsics */ \ + 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(_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 3184e2ee86cf6032f1188e346f07bd3e60a6dca7..ec3e3a8e072e19c97ac81347189001b95f5dbef4 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 d4d946e833655364057295d41ec36ccfe6a8b761..cd1edbbaa36d889e11fb6d43743aead47d997e06 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 f1cbf02223fcf6247bc418a3f1f83c805862dbcb..e82d9801d1281c3e36c2307417cc9c60ed1f7852 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 62930adbc7931b1aaebe2a66b9fcf7740b0b290a..d8daac3a0f2fd05ef7101e1378cf28d4a824755a 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 ed77e17b7f5e1ba4373ed3d4df18a44affa7daef..c941f40427622f8d1920465588c6f3869306d39a 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 a2ffeeb08d1383c0f1b770c8de7fba95e9d43817..e9c26011695f91ef36f72fa60ab1c90b3ab4d8fe 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 04f3f31460300e32503fab20a06d4a5d45099547..788cca8b002d643a55d2cee5f3018a7481647950 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, @@ -1350,20 +1350,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 +1522,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 +1608,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); } } } @@ -3004,7 +3001,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 +3381,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 2125d9680bd4dbe4c481e1c7d493dfed727dad81..9510caed36e4b9ec7eac23e2a48301aa11afe4a2 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/compiler/abstractCompiler.hpp b/hotspot/src/share/vm/compiler/abstractCompiler.hpp index 1c5304f6475a2181e0efccfd87130bf555ba0dbe..b02d85eaf5774a60c4ee040f73d343e6b5e7ab70 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<mtCompiler> { // 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<mtCompiler> { // 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<mtCompiler> { // 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<mtCompiler> { 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 7e28599fda190c1269adf96de565b1b5c2f5ad44..b508b2e893cb2fc601b11f9a23c4333ecb0ba62f 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 b469aebd769ad1a15e618eb9d50c6f52ea44e498..9c0709aa28f5424c3d8a2ffe157bfef8d6968469 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 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 void preload_classes (const methodHandle& method, TRAPS); + + 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 a01b960899c05fd235ea2400128b86245c9855fd..0cd15c9592e06f09876a6cf52dca11e21d058193 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 68c933861873bf895090728077c3595951ef9559..b35d134509592d14f241f464ce3eec2487f120b7 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<mtCompiler> { _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 471249305afb6b6bcac7d8c5109a5c8716e2b886..15d5d3a091c0241b910d894e2a158c07f83dffda 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<typename T> -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<T>()); if (m != NULL) { @@ -333,19 +333,19 @@ bool CompilerOracle::has_any_option() { } // Explicit instantiation for all OptionTypes supported. -template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value); -template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value); -template bool CompilerOracle::has_option_value<bool>(methodHandle method, const char* option, bool& value); -template bool CompilerOracle::has_option_value<ccstr>(methodHandle method, const char* option, ccstr& value); -template bool CompilerOracle::has_option_value<double>(methodHandle method, const char* option, double& value); +template bool CompilerOracle::has_option_value<intx>(const methodHandle& method, const char* option, intx& value); +template bool CompilerOracle::has_option_value<uintx>(const methodHandle& method, const char* option, uintx& value); +template bool CompilerOracle::has_option_value<bool>(const methodHandle& method, const char* option, bool& value); +template bool CompilerOracle::has_option_value<ccstr>(const methodHandle& method, const char* option, ccstr& value); +template bool CompilerOracle::has_option_value<double>(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 454fc6317d4d07d13da105b8dbb9c5e81ef87f34..9b731ebb2e0fe25a024f4d2c26569f05bb3b74d3 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<typename T> - 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 82b0291f2d6747765fcb1a5875f03ebf3974d6d7..1ac15590cd0c0118620ec2c94f1dad5d5e97c7c3 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. <home>/jre/lib/<arch>/<vm>/libhsdis-<arch>.so (for compatibility) diff --git a/hotspot/src/share/vm/compiler/methodMatcher.cpp b/hotspot/src/share/vm/compiler/methodMatcher.cpp index a8a342ec9b2cb3e1636d3cc187544d1adef56880..51d38c7caec8280e224dca2c48d38567d6309b5d 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 938a14b0a551202ed87c0a72b780783e74199252..546af4d5ed783b46daf47df293b0b6ac6fc3d3d6 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<mtCompiler> { 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 080f80d4825a0693f96bf58718449c546b9a8d98..5428f3bdee22f58c8caf11becaa062fa08331c13 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 d924ed27bafe15c8a1861baf1a06f38a133849a3..933186d34fe171332e758a2715e5d5be71d5346c 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<FreeChunk>::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<FreeChunk>::dictionaryBinaryTree: - _dictionary = new AFLBinaryTreeDictionary(mr); - break; - case FreeBlockDictionary<FreeChunk>::dictionarySplayTree: - case FreeBlockDictionary<FreeChunk>::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<FreeChunk>::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 52213970689a8ed19c7c237b171a2bebd4893337..3cfc3a665f52933a0808851a088303fe01e84f5f 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<FreeChunk>::DictionaryChoice _dictionaryChoice; AFLBinaryTreeDictionary* _dictionary; // Pointer to dictionary for large size blocks // Indexed array for small size blocks AdaptiveFreeList<FreeChunk> _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<FreeChunk>::DictionaryChoice); + CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr); // Accessors bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; } FreeBlockDictionary<FreeChunk>* 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 d29415817b553589731abe358ae13de25284d0ae..25f3d2fd4356f497ece9b28d9f4833e340029c61 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<mtGC> { }; ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration( - ReservedSpace rs, size_t initial_byte_size, - CardTableRS* ct, bool use_adaptive_freelists, - FreeBlockDictionary<FreeChunk>::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; } @@ -1766,9 +1755,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 +1783,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 +5202,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 +6173,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"); } } @@ -7372,14 +7350,6 @@ void SweepClosure::initialize_free_range(HeapWord* freeFinger, set_freeFinger(freeFinger); set_freeRangeInFreeLists(freeRangeInFreeLists); - if (CMSTestInFreeList) { - if (freeRangeInFreeLists) { - FreeChunk* fc = (FreeChunk*) freeFinger; - assert(fc->is_free(), "A chunk on the free list should be free."); - assert(fc->size() > 0, "Free range should have a size"); - assert(_sp->verify_chunk_in_free_list(fc), "Chunk is not in free lists"); - } - } } // Note that the sweeper runs concurrently with mutators. Thus, @@ -7532,12 +7502,7 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) { void SweepClosure::do_already_free_chunk(FreeChunk* fc) { const size_t size = fc->size(); - // Chunks that cannot be coalesced are not in the - // free lists. - if (CMSTestInFreeList && !fc->cantCoalesce()) { - assert(_sp->verify_chunk_in_free_list(fc), - "free chunk should be in free lists"); - } + // a chunk that is already free, should not have been // marked in the bit map HeapWord* const addr = (HeapWord*) fc; @@ -7550,57 +7515,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 +7542,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); - - 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); + do_post_free_or_garbage_chunk(fc, 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); - } assert(_limit >= addr + size, "A freshly garbage chunk can't possibly straddle over _limit"); if (inFreeRange()) lookahead_and_flush(fc, size); @@ -7727,11 +7608,7 @@ 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"); - } if (CMSTraceSweeper) { gclog_or_tty->print_cr(" -- pick up another chunk at " PTR_FORMAT " (" SIZE_FORMAT ")", p2i(fc), chunkSize); @@ -7739,7 +7616,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) { @@ -7784,10 +7661,6 @@ void SweepClosure::do_post_free_or_garbage_chunk(FreeChunk* fc, FreeChunk* const ffc = (FreeChunk*)freeFinger(); assert(ffc->size() == pointer_delta(fc_addr, freeFinger()), "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"); - } _sp->coalDeath(ffc->size()); _sp->removeFreeChunkFromFreeLists(ffc); set_freeRangeInFreeLists(false); @@ -7856,12 +7729,6 @@ void SweepClosure::flush_cur_free_chunk(HeapWord* chunk, size_t size) { assert(size > 0, "A zero sized chunk cannot be added to the free lists."); if (!freeRangeInFreeLists()) { - if (CMSTestInFreeList) { - FreeChunk* fc = (FreeChunk*) chunk; - fc->set_size(size); - assert(!_sp->verify_chunk_in_free_list(fc), - "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", p2i(chunk), size); diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp index c846cb48308ec3a4ea96497282e1dea16d15317e..1f0be952fc5bc33fe1d496cadf2c5966cc83ec40 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<FreeChunk>::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 807284c0edc854e9923a83797fa366d8c5cd04df..82f9e51a6b2e313bf6ed89f82c4e8f9009b4a93d 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/vmCMSOperations.hpp b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp index a0a62181e894717ffd940af7c7f322c64c925f9e..dc262c25b7b90c3a16a1aaa092eed7b1eb841f60 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 ea67798bbb57d2576f66a405da60715e2662d204..0e2f4dd4bb3405728bda23f5337e45de0dc9118f 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 b10aa68f53bcf65a3a4f9ffb9c368c001d5893df..0e5525f73c2721b5500e916fbdfe420138a944e1 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<mtGC> { + 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<mtGC> { // 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<mtGC> { 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 f652cf97d06ff00a56355831bd32820704024cac..a65b0638a82463ea6e0a8fe42a7a878d89b01a78 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<int>(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<int>(_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<int>(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<int>(_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 cbaf3c3d78254a8e36af2ab7ae518326da221c81..5b6d3ed79d54999e467391b6ff1415a17d0c33c1 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/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp index 36dd7fc29bbc29400d5b51294d41c6544999b925..4884a7742fdcfc8b2db1e3412f1ba18c6caaf378 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 afcb3f13e8f96832b2e61b04db15beba5f65b1a5..13f34d676a9098a8f1ebc549357312c9b893f017 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/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 4b36a61ff683471036c56ae135e0974b93642dda..6383e4d6cdb00183762f01c19ae8e147ac806c4c 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1716,7 +1716,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 +1733,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; @@ -3930,9 +3934,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 +4005,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 +4594,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<InstanceKlass*>(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 +5170,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 +5242,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 +5261,23 @@ 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(); + + // 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 diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index dc4c5ef1a80c5b29f7991db233f3f24c1b066841..410fe4dad625e74e7e604729fa20a8ef57b00a57 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); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index 41cdd6c5a335cb9b1a0922093d0528436592bac1..3ec0e0406b686d840ca97b3b3bec6bd351df1ae0 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -431,7 +431,7 @@ 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(); @@ -507,13 +507,24 @@ uint G1CollectorPolicy::calculate_young_list_desired_max_length() const { return _young_gen_sizer->max_desired_young_length(); } +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) { - 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); - } + _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 +555,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 +579,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 +704,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, @@ -801,7 +820,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(); } @@ -879,6 +899,10 @@ void G1CollectorPolicy::record_concurrent_pause() { } } +double G1CollectorPolicy::average_time_ms(G1GCPhaseTimes::GCParPhases phase) const { + return phase_times()->average_time_ms(phase); +} + bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc_word_size) { if (_g1->concurrent_mark()->cmThread()->during_cycle()) { return false; @@ -1049,16 +1073,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 +1124,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 { @@ -1109,8 +1133,8 @@ 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)); + (average_time_ms(G1GCPhaseTimes::UpdateRS) + average_time_ms(G1GCPhaseTimes::ScanRS) + + average_time_ms(G1GCPhaseTimes::ObjCopy) + average_time_ms(G1GCPhaseTimes::Termination)); double young_other_time_ms = 0.0; if (young_cset_region_length() > 0) { @@ -1147,12 +1171,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 +1192,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); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp index 8904170bcaf0c1e6a9992c80530ff25eaf62e204..c04bcff676a81937fe5fded6a3c4fac183f277cb 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,9 @@ public: double accum_yg_surv_rate_pred(int age) const; +protected: + virtual double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const; + private: // Statistics kept per GC stoppage, pause or full. TruncatedSeq* _recent_prev_end_times_for_all_gcs_sec; @@ -465,12 +468,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 +500,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; diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp index 349982f4f9d4bd3c8cfc259f96f2dc9b7bfe756e..de0e5eda2962e8532bed426d68e6a93d3d3d0c7e 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 c9d6ae92c553742265cbde2878d7584cc1817e52..f34ebb7ed63af6585f5dd0545a45f1e56944073a 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 T> -class WorkerDataArray : public CHeapObj<mtGC> { - friend class G1GCParPhasePrinter; - T* _data; - uint _length; - const char* _title; - bool _print_sum; - int _log_level; - uint _indent_level; - bool _enabled; - - WorkerDataArray<size_t>* _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<size_t>* thread_work_items) { - _thread_work_items = thread_work_items; - } - - WorkerDataArray<size_t>* 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<T>::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<T>::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<T>::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<size_t>::uninitialized() { - return (size_t)-1; -} - -template <> -double WorkerDataArray<double>::uninitialized() { - return -1.0; -} - -template <class T> -void WorkerDataArray<T>::reset() { - for (uint i = 0; i < _length; i++) { - _data[i] = WorkerDataArray<T>::uninitialized(); - } - if (_thread_work_items != NULL) { - _thread_work_items->reset(); - } -} - -template <class T> -void WorkerDataArray<T>::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<T>::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) { @@ -298,6 +140,7 @@ void G1GCPhaseTimes::note_gc_start(uint active_gc_threads, bool mark_in_progress 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; } @@ -536,6 +382,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 87752426d04f92efcc4fae8f92280ca53d13414d..a9159715156317b988977964330c44f90367e8a6 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<mtGC> { 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; @@ -155,6 +156,10 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> { _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 +257,10 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> { 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/g1MMUTracker.hpp b/hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp index 6edb16bf1c75a622d1d7818689e869b345d81825..c8a09af2adcc4749357356ab142a1f1e38e846e2 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<mtGC> { protected: diff --git a/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp index 202bf8f6f9f81e556fa5fdce72501c99dabe4b6c..276cbabeca76b5950c31dfd1ab0ed9d8d913810f 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 56f1c2d1c06a7e5f7ce6aa7754b96d5616ac9316..1aff126f813f10aff7677f8f4adb3bcbbf465c07 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<mtGC> { 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 0000000000000000000000000000000000000000..cc0506da12afbffe6762015ce8d9a837fd26bba5 --- /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 0000000000000000000000000000000000000000..0e251451c0242cd83277af373d67eef34d50a2cb --- /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/heapRegion.cpp b/hotspot/src/share/vm/gc/g1/heapRegion.cpp index 75e017ff3c24fd404d290240bebc44fc34f5d5be..565300f88aa300fcf87b360122e9875435187cb3 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp @@ -660,7 +660,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); diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp index 3186ff9f31153a2730351ba3837271edb0e0f803..5d1c0048b36b13d4113abbf0a4aa00d334fc8f2d 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp @@ -563,7 +563,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,6 +599,7 @@ 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(); @@ -1138,7 +1139,7 @@ void HeapRegionRemSet::print_event(outputStream* str, Event evnt) { void HeapRegionRemSet::print_recorded() { int cur_evnt = 0; - Event cur_evnt_kind; + Event cur_evnt_kind = Event_illegal; int cur_evnt_ind = 0; if (_n_recorded_events > 0) { cur_evnt_kind = _recorded_events[cur_evnt]; diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp index 3b07c65d1bf37b3d2a7575ca47ba08221147524f..70ad79734de3c69cc5fffed91032d1626ecd35f8 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp @@ -222,7 +222,7 @@ class HeapRegionRemSet : public CHeapObj<mtGC> { public: enum Event { - Event_EvacStart, Event_EvacEnd, Event_RSUpdateEnd + Event_EvacStart, Event_EvacEnd, Event_RSUpdateEnd, Event_illegal }; private: 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 0000000000000000000000000000000000000000..420fc9c6ef8db3c968a331cad1c14b52626917bc --- /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<size_t> 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 0000000000000000000000000000000000000000..c96c4f9e65de8fec92ebcc46787deb9de0913673 --- /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 T> +class WorkerDataArray : public CHeapObj<mtGC> { + friend class G1GCParPhasePrinter; + T* _data; + uint _length; + const char* _title; + bool _print_sum; + int _log_level; + uint _indent_level; + bool _enabled; + + WorkerDataArray<size_t>* _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<size_t>* thread_work_items); + void set_thread_work_item(uint worker_i, size_t value); + WorkerDataArray<size_t>* 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 0000000000000000000000000000000000000000..a228dc2309ff649e3ce2abcbc6a469613a8574c0 --- /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 <typename T> +WorkerDataArray<T>::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 <typename T> +void WorkerDataArray<T>::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 <typename T> +T WorkerDataArray<T>::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 <typename T> +WorkerDataArray<T>::~WorkerDataArray() { + FREE_C_HEAP_ARRAY(T, _data); +} + +template <typename T> +void WorkerDataArray<T>::link_thread_work_items(WorkerDataArray<size_t>* thread_work_items) { + _thread_work_items = thread_work_items; +} + +template <typename T> +void WorkerDataArray<T>::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 <typename T> +void WorkerDataArray<T>::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 <typename T> +double WorkerDataArray<T>::average(uint active_threads) const { + return sum(active_threads) / (double) active_threads; +} + +template <typename T> +T WorkerDataArray<T>::sum(uint active_threads) const { + T s = get(0); + for (uint i = 1; i < active_threads; ++i) { + s += get(i); + } + return s; +} + +template <typename T> +T WorkerDataArray<T>::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 <typename T> +T WorkerDataArray<T>::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 <typename T> +T WorkerDataArray<T>::diff(uint active_threads) const { + return maximum(active_threads) - minimum(active_threads); +} + +template <typename T> +void WorkerDataArray<T>::clear() { + set_all(0); +} + +template <typename T> +void WorkerDataArray<T>::set_all(T value) { + for (uint i = 0; i < _length; i++) { + _data[i] = value; + } +} + +#ifndef PRODUCT +template <typename T> +void WorkerDataArray<T>::reset() { + set_all(uninitialized()); + if (_thread_work_items != NULL) { + _thread_work_items->reset(); + } +} + +template <typename T> +void WorkerDataArray<T>::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<size_t>::uninitialized() const { + return (size_t)-1; +} + +template <> +inline double WorkerDataArray<double>::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 9293a84cf48ee91933a9d01ca33375102f7e429a..1047e0bbc7f01b4e1a9287f2005fe21276018cd3 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/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index 29f3aeb65a032bb8ee9c1e50925fa198c16c178d..fc4181ef307144882a9c4c2cb54026cca2097d1b 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 f9ec569dbcaa4cbc8fbdd5e5042644eab9ff814b..03b9e3daae1341b73d35684fcf5c7e58a16ee148 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 f85e798de4e13fa1bfa24f3b2ebc288bb2933c88..1eff9c9fa3a42e0cd06817141f6e17405f67b172 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 f9b86321fe19e463557b6944f89285a621bb6842..11146d8750e4195a013e0db40e7a9dabcf435659 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 c4ab3fe7862880aeac9c888892a9abbcff3e674f..5724808b1420dd0810f6afcac3c3880dfbaa5f2b 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 e7df6cd57dde4813c9de14a1f59b730ae4c2e5b0..954bc8ad281809999c9c207dc0e9a379a6488a60 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 c18734ec77dddda01256bd4037a4b805ea676aae..8663f5449cd0a3eb1d94003c3aee965d51f091a0 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 8a21dbb2977b937e3d700b658c22bb806c9b2b0a..7e35485510b95fd2ce1c7989f2ce65360a128e06 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<mtGC> { } 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<mtGC> { // 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<mtGC> { // 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 a243d674c582b60ea07e508a0d62598a5a968ee4..31de065cb0a2e0f25f4f2130c1dccd77474cd5dd 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<FreeChunk>::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 ba2cd40f35b2aae13fa175b0db698aed7a097764..684b64e2b21b0595128db8941220835d85aa8c1f 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 4acda1233fa1e6b737463f62381558bf3e6c5fda..e43d42d2d6df14c0a10a66bab5a4f7e617742bde 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 0708816ff519b33f9ec74e844228ccf5c634265c..f3fc9ea9d6a1bce0ec27e0214edcfb4042a061b3 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 a9252c2bfa73d3d94373743e5290168e5ae4332c..c81436abc2436242f9986ae3a0688f0504400e2f 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 @@ -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 1f657b98bc2d6e81fc82d13a0fcba9b14c55e31d..65a0aa4631a1282b0acec2241f92160feb395f3f 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 a0d52b0d196d65d20a2ed05bf73f9be83b36d3ce..a1ae0eee4a6ee28117e2255b4875f23f2fa600d5 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 9e5837139a22f749de25890c6bcad1329e753a66..06d2a1d8899db5048a3984dd73139d0b25e75dde 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 eada76cb3bb634fe434432558c473feed88ff899..1f4e08bcd436d187695b7d7e58286ea93d1be4c6 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 ebc4832283c088cbef97de58660100e7cc16d6d3..60991b96ca83285d7de4b0a11f4b87ebd5e62d9a 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 bdbde617cba2730936330cf595a092cf6f893111..297102c4f1a9167cd86401a66028d2d9c9a364a9 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 7988d6f5f87baedee619346ba35e45d5d6e63068..173ec0ec66708d69667036d05fe73b2bec0e25ae 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<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods(); + Array<Method*>* 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 77cd163254973392a8ec007d27947717d486a48b..198eefbe2c049400c92e7b8e9cfd9ed5d7c0388f 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 2233f1b0f3ff0d08ace8f54a2121347f0da98b2b..7dcf024532edfe86e102792eff6c1c908f5339b9 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 19bf0044925129ad4e4bfb6591c81c17996a0adf..cb9367e150f63b516e9136e83c8df9a8a7ec3e99 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<mtClass> { 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<mtClass> { // 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 01122e7ecf77e204e304e89027f6a4292399ef38..e5e51af1e2e58c98949e48bc92adbe5303ed4052 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<Method*>* methods, TRAPS) +Rewriter::Rewriter(instanceKlassHandle klass, const constantPoolHandle& cpool, Array<Method*>* 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 aa4b7cd5228193f46ae05febc6d697c16a5d22a3..de25b101e846ac935acb73574c834b493f839cda 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<Method*>* methods, TRAPS); + Rewriter(instanceKlassHandle klass, const constantPoolHandle& cpool, Array<Method*>* 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 8d75f5e1ed4c5b8b47e11fc43282fad3341a9f88..73beefc6766f3e5e7badf0047db70d5d378bc4ef 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 bbf5e992f583571271a07244c1ee334a2bd32b16..3a46b2281fde64ebf395fe51b2e345d3fb59bc7c 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); - } -} - -// 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"); - - record_metadata_reference(obj, prim, false, oop_recorder); + fatal("unexpected metadata reference for constant of type %s", obj->klass()->name()->as_C_string()); + return NULL; } } -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); +#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()); + + 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 b0d3016b645519cf7d9a736c9161ca03d5747eb9..2ee2cbd742c8fd83bf89ac328fa9772058854b3e 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<ScopeValue*>* objects, ScopeValue* &second); MonitorValue* get_monitor_value(oop value, GrowableArray<ScopeValue*>* 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 7cb959a96b82e8e1ca80d4d72ff139276276a2bf..7fdf21e60eeeb6db84aba8cd33d731bd93989cf7 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<Method*>* objectMethods = InstanceKlass::cast(SystemDictionary::Object_klass())->methods(); + Array<Method*>* 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); - - _methodsCompiled++; + // 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; + + 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 b4d3a4964bfc1925a8d69751497abcfddbf7d69e..0b0a38d5afa311075748ebec457e1ceaed085f6f 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 2430d33a3c85d5d0690c6308cee5a0ce87c3e7d9..c0f773e279baf67e5cdf834c5d6a5fddf753c75d 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 bf6cc6bb3a044960fe3dc97e6750a52dc48d62b0..4acce0bcb9373f1ea39537a8e6dd01a035d74c05 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 9758ce6d7bb880e8a6f4f6211323d2aca8bbb0a3..348a28601be3c56524935c3cea8cfa8e4d6ecf79 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 <array>.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 db88196310a814be73f25190b16082c67803e714..f0291efde26af4e1ab28abb2133c7665762dc230 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 928fc1d1440395a579cca7ebd039f52a0fac8a0b..190aaf419f1f5c0c64a1e1b13f7c4a4064d0b03a 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 bfd81623cd8b2af753b0c2cd858ea920b9bdcae8..22f6bede11869f8377d9433786890d7616ad1bc7 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 d436a265cc703e1c22df855da135535eb6860e8c..55632f2acb9a026b6977326082eff313f5838d0a 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 df41d67688eb2cf75376fed62ea302a27f95c9db..00eae524c1598b711c3c99efebbe9447f65b04ce 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 931dcaffb9cde0536365474e52a7f91174682cb5..58701527f0f19c3af9af7078d7acb6cf8d5f89a1 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 97ef4466fd948d5f43f83ef097accf9549ceec45..a58a6ef74c7ccd3f9ea1ce45905b16f1d8a963ed 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 eedc51b6e86f5c15747a0350b070b03fd9b90d88..5502f2fa6030e6fcca5cedd06d0b22baa4b9b455 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/memory/allocation.cpp b/hotspot/src/share/vm/memory/allocation.cpp index 5f846d3c245a606ace7725529e4a1be6c55efc7d..b6287bd5ed1253b7d1c093fc090e72fdb2ffc2c2 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 c152f6ab525b3c9aed26c5310b61c8720546675d..9113fb02b17ce3ee2ad1568125cecef0826ee617 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 e026c565b1dc163702f43bad69308d38f584b3f9..8c725cdac02bda969e97476c53e7fa1ef9dc64f4 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 6f24c4917af9d48647f2bb5ac020b137931f33a5..d120a45218f6cd35d791d0fc232edcd4a66247e3 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; c<KlassSizeStats::_num_columns; c++) { -PRAGMA_DIAG_PUSH -PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL - if (selected[c]) {st->print(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 9e312206b2e48c03db5b8a1e3a72c4366bddecd7..97197b1bc5e362e898f0316646222441811cb5cd 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 71507120a70c84a591b41d0745df70078b8e9e7b..0af64dbed96d1b977f62a5bdf2cc2f3c9388e90f 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<Klass*>* _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 1e214b328d3e479db6fc88638a66052ad46eb1f5..3693deb50077e040cccb9ec1dd9a241c2812fd5e 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 fa22f5bfdcc098e2a6e4d872b16abbb883e15a5e..7ec9cfa3a9928256b7f63be55f08956ae5a45c48 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 e81a353f53ba0cdfe6468e988ed9a607bb83a03a..0a9dbd28cc44e8933ca33557413fcbded1dd0bc1 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<ArrayKlass*>(k); } GrowableArray<Klass*>* 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 5d3c61d2a41d2d4439031dfccb057f56a8182f27..006a1e5b5a63ab1c6184536c5e073ca0c17d14fa 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 dca3a2f4d31a8427cfc4b303d4f10fce639a175b..99d77253be9c1314a8a4550bde24b748311a6919 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 db65df2172c61bcdd967199ba69948c8b1b370a8..6066a319e8fe4702cea3f3ba489b6a7c51c8cfe4 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 435a1d6c4a7abf64f3664d0607ba48411f76d0ea..cf6731da6135d07a794797242bef5d97346d5f22 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 40a192bdcc0562e9526917611a320f959a021ff6..cf456667a78a8fddb74bb716ad968a5bda6b782d 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 342c31f4fad01bbf3d70f6bab266202e2fd9b50b..c7d2d2743cf172d2735f1265aa00452a5bd7b631 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<u2>* fields, constantPoolHandle constants, int start, int limit) { + FieldStreamBase(Array<u2>* fields, const constantPoolHandle& constants, int start, int limit) { _fields = fields; _constants = constants; _index = start; @@ -91,7 +91,7 @@ class FieldStreamBase : public StackObj { } } - FieldStreamBase(Array<u2>* fields, constantPoolHandle constants) { + FieldStreamBase(Array<u2>* 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<u2>* fields, constantPoolHandle constants): FieldStreamBase(fields, constants) {} + AllFieldStream(Array<u2>* 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 2207e8c814e7c387897096d920a48edfc94b7a4e..53ec05ef6ea2211e1adf4d64e922c7d7612f13f8 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 48c49f443e93ebdfcdbdcba664f8dca581d39327..8822ee0d839d506ed862a225846cfaecbc2b77f4 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<intptr_t> *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 f01521cc0096b54c893d90f1f9bd63d052b9c532..03584ee032030e95bf9cf6ed68773a74a13aeacc 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<Klass*>* InstanceKlass::compute_secondary_supers(int num_extra_slots) { // The secondaries are the implemented interfaces. - InstanceKlass* ik = InstanceKlass::cast(this); - Array<Klass*>* interfaces = ik->transitive_interfaces(); + Array<Klass*>* 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<InstanceKlass*>(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<nmethod*>(0x8 * 0); + _nmethodMiddle = reinterpret_cast<nmethod*>(0x8 * 1); + _nmethodFirst = reinterpret_cast<nmethod*>(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 be9501089b64385c5281d7a0b278d23cf6b946a4..9eebfcb7010869809f01d3b691cda65912a7ac3d 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<InstanceKlass*>(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<mtClass> { 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 aa64aad4e01cda65eee9b2d66cd5c226a9db1c92..107f952329672a42118e4a47de79f0dffeb3be93 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 9d1e9c622be7c8ca4b6fc1c5cd0c062a5d7d820e..cb416918d9e4ef94e0afe20d0582949e6a041e7e 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 31da264eeffcf07a0a45465039ec512f689edc9f..8dc309dbee2023f52e790c574bd8ae3fe9398cc0 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 30bdc14cd2af5df42afff3f6da97a49a7240d037..273c6c062bc39d712e830eb05910292b979be504 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -348,7 +348,7 @@ GrowableArray<Klass*>* 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<const InstanceKlass*>(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 aa8aabb61faf346ce065a6e740949586358d2fa9..a7ddf019063bb7675d66b2ff4922fbbd5f6a882c 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 5c820f574c183b36a887fa5496ae7a829dc48308..5609980579f675ac2ecae85e996d8ca082d08aba 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 9872b3fca5571735719c1f7047d0b26b66259d5f..7f6ae730c2e427d1725f2583954f1390f07a2749 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<Method*>* 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<int>* def_vtable_indices = NULL; bool is_default = false; @@ -761,15 +755,14 @@ bool klassVtable::is_miranda(Method* m, Array<Method*>* 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<Method*>* 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 192769f72263b79c525df887463390cfed0a4c84..1c175b06f981939718b0e115e472ea16745d05bb 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 f1a2e916f7d8ca2a403a47efdfe3d0ca1c1a534e..b0cd50ec0c6dcc67fcd2c3974f0b02f52a96e2ac 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 c74a611ffe1662c61515916261377c08f3dbb0c1..f460028393fe1c4ba2a30e7d3fb632113af7b3ea 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 ac58123f8b7c3b161284499bbe13070d94e6c172..14afeccea57b4fa9d372b61b6b3174e4b0162292 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 eb7a84e192aaec56490aa1da34abe06451607d21..bd696d5cc0f826ae807a382ff97b19e75cf4afc1 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<Klass*>* 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 fa4a37b7556fca7d3c6d93ac62112c89c7543364..d888fb7228a40f158c86bdce6340a89bb41501ed 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<Klass*>* 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<ObjArrayKlass*>(k); } // Sizing diff --git a/hotspot/src/share/vm/oops/oop.cpp b/hotspot/src/share/vm/oops/oop.cpp index e801ae30229e49df7b5fbb751811f061ef2fbbfb..18d1f227b48a0c1559d4104894fee3414b258d06 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 ed969cf6f7f1e829ff43d1af070f4df99563691d..b096f3f45c54524469ea6590f11cb7ac736ab306 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 4ab957dbd26f734aef78d64a230c98e8bbb0fa7d..bc480f49deaa2fccf76b00e348e880a2b4305aa0 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 8b1453ff6c6e09b3e93c179b738351a06b57fa72..2e76bc4d96a4db973fcb08e36d487fb99ff5bace 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 1ef2775b2fcbb2c615177dee620caccdd2172e8a..f794b60326b2e3168c00fa365cc241d01b1a23ae 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<TypeArrayKlass*>(k); } // Naming diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp index 7d61e8946a25378a20c224e3763d195999978a1a..57036c2c0c83d8b34b95cb03f54fe3b95deb181c 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 9dfcd5c79e31fea66851d2632335f7c8a1e726e6..60f1f2002482d603e3fbd0672ea317a06e2a81ca 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 016b4908e33b21c9e8f53c9738966097ada704f6..9df31b4f712cac32d7769704de560b11549e7746 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 7e569551c793b8808b605a850399ae65f07cbd66..ff86ad4750d475683757e10e676b7764f561d074 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 4464d6a8b6a5756830c4f34e9f097563af89dd6c..754c8f6a08faac813a1631b2ec27c1b07b0181d0 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 94a97e3d5ae472e320651e049b54a3835af7ce3f..032fe0a6f6fc524315e4227a8392ceeda5f53dfc 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 511d8b1f046ee9bf6c4ac3be5b3635e22b23a7db..27342ed12be85dce871348f52e43c92e5e1b06d8 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 f1db509489d7d86feb7eb7ff05cf8865e61ab4f9..fac8c4d67fec33a909ce71a1c7681be3d607ec4c 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<Node *> &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<Node *> &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<Node *> &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 e73494b45e344ea92f085fe252e5f2edc54d3987..70c17ad8b1c8e5042cb099f3938f9733dccf720e 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 5603ffbbd273a16b741174f522706b6ae4c2bbbc..b3bc8999daa6c7d62b1b28656d00c241988edc06 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 3ccdcf6dbe32679576486f070ed627ae4c3d9f53..397e6cb1c81df1e8ed91d2acc8ffa8e71a345b68 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 24dbba08a115adac1808c6416edb334637e88e40..a47047d64aeb0b257dcdcbc5ea41f11c36aeea74 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 3038982e648e72975a726e2876679debd7e95652..cbba57eba9531ec25b8cf8b4d7007974c1b94241 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 3828d30cc0b6d9bc09cc404eae39583095eb0480..73db477150996cbbe1ee2e28f9074e08444f59e5 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 683cad55fedff4807ee813509e4f245a0a9bcf53..e72c3e221e180898c2a130ebb6a5ff7e20a43e52 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 2f19db6474b66bf076a33ea5071bd2a58aea96d5..d5bc0c707420ee89004d8b44504efefcadc5871e 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 01a21cd48e90728a38f07aa705a25a911f9849b6..1dd92fa610f00176d0db3948d53614535f7171fe 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 4c27dab9b035e66f1c500a07c86359de3c7693a4..c1f744c5be0e5fe8eba2148be96635bbb9c81bf8 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,45 +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; +// 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: - // 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); + result = new StrIndexOfNode(control(), memory(TypeAryPtr::BYTES), + str1_start, cnt1, str2_start, cnt2, ae); 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); + 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, str1_len); + result = new StrEqualsNode(control(), memory(TypeAryPtr::BYTES), + str1_start, str2_start, cnt1, ae); break; default: ShouldNotReachHere(); @@ -927,129 +939,55 @@ Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2 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) { - Node* result = NULL; - switch (opcode) { - case Op_StrIndexOf: - result = new StrIndexOfNode(control(), memory(TypeAryPtr::CHARS), - str1_start, cnt1, str2_start, cnt2); - break; - case Op_StrComp: - result = new StrCompNode(control(), memory(TypeAryPtr::CHARS), - str1_start, cnt1, str2_start, cnt2); - break; - case Op_StrEquals: - result = new StrEqualsNode(control(), memory(TypeAryPtr::CHARS), - str1_start, str2_start, cnt1); - break; - default: - ShouldNotReachHere(); - return NULL; - } +//------------------------------inline_string_compareTo------------------------ +bool LibraryCallKit::inline_string_compareTo(StrIntrinsicNode::ArgEnc ae) { + Node* arg1 = argument(0); + Node* arg2 = argument(1); - // All these intrinsics have checks. - C->set_has_split_ifs(true); // Has chance for split-if optimization + // 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); - return _gvn.transform(result); -} + // 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); -//------------------------------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)); + 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)); - - Node* inst_false = generate_guard(bol, NULL, PROB_MIN); - //instanceOf == true, fallthrough - - 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); + // 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* no_ctrl = NULL; + // 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); - // 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; -// } - -//------------------------------string_indexOf------------------------ -Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_array, jint targetOffset_i, - jint cache_i, jint md2_i) { - - Node* no_ctrl = NULL; - float likely = PROB_LIKELY(0.9); - float unlikely = PROB_UNLIKELY(0.9); - - const int nargs = 0; // no arguments to push back for uncommon trap in predicate - - 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); - - 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); - } - - 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_); +//------------------------------inline_hasNegatives------------------------------ +bool LibraryCallKit::inline_hasNegatives() { + if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; - // Final sync IdealKit and GraphKit. - final_sync(kit); - Node* result = __ value(rtn); -#undef __ - C->set_has_loops(true); - return result; + 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); + + RegionNode* bailout = new RegionNode(1); + record_for_igvn(bailout); + + // offset must not be negative. + generate_negative_guard(offset, bailout); + + // offset + length must not exceed length of ba. + generate_limit_guard(offset, len, load_array_length(ba), bailout); + + if (bailout->req() > 1) { + PreserveJVMState pjvms(this); + set_control(_gvn.transform(bailout)); + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_maybe_recompile); + } + 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; - } +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); - 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); - } + // Make the merge point + RegionNode* result_rgn = new RegionNode(4); + Node* result_phi = new PhiNode(result_rgn, TypeInt::INT); - 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); - } - } + // 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); - 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; + // 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); } - const TypeOopPtr* str_type = _gvn.type(arg)->isa_oopptr(); - if (str_type == NULL) { - return false; + } + + 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"); } - ciInstanceKlass* klass = env()->String_klass(); - ciObject* str_const = str_type->const_oop(); - if (str_const == NULL || str_const->klass() != klass) { - return false; + // 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); } - ciInstance* str = str_const->as_instance(); - assert(str != NULL, "must be instance"); + if (stopped()) return true; - 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 + // Range checks are done by caller. - 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(); + 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 { - o = 0; - c = pat->length(); + insert_mem_bar(Op_MemBarCPUOrder); } + } // original reexecute is set back here - // 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; - } + C->set_has_split_ifs(true); // Has chance for split-if optimization + if (!stopped()) { + set_result(newcopy); + } + return true; +} - 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; - } +//------------------------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; - // The null string as a pattern always returns 0 (match at beginning of string) - if (c == 0) { - set_result(intcon(0)); - return true; - } + // 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); - // 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))); - } + // 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))); - 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; + 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; +} - result = string_indexOf(receiver, pat, o, cache, md2); +//----------------------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 02153bf31e602a192e63cd736d89273893ca26d8..735a00dd1a12677428e51904fcde47e90cd1be3e 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 9c09c888f2cf1211bbd59d4eea34557c9f82a8d3..eb09d62d23a698666272ec4a6ca2907628475484 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 783ba1d3eeb672c4facb96e506479bc3b552f760..bd5ceaa9b7af5a59dd7c295d662090fb7f2e2f33 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 <Sa ciKlass* klass = NULL; ciInstanceKlass* iklass = NULL; int nfields = 0; - int array_base; - int element_size; - BasicType basic_elem_type; - ciType* elem_type; + int array_base = 0; + int element_size = 0; + BasicType basic_elem_type = T_ILLEGAL; + ciType* elem_type = NULL; Node* res = alloc->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 684af2a82e4aabe1c4b6bb28709ff3f0cf3eae21..117dd765ac8826ee2d133f798139a4a0e908dd65 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 1abfede267b5b4674c884acff0017b063e13735b..b9b5838eca4b881b427d56194da6bfd279a63906 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 3a07d9f707cb27c0abf31997aecadecc780a5b14..99a3734ba46b4efa9e505eec132343ea6fbe38ce 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 b555ae00e9b68dd0fcd8dedf7757eed7f02f5bc9..1ae727c105a2e4089df6a60b0e358f591f1c7083 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 40a762b03a380a1c8cc82f3e90a476433f9b2654..215832d68cf825e8ba998700b432aed5cb021ff0 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 4e67f5151fe0c0770f05f35499ac524bff6bea68..b11742f04b31de30bebe6f99c2d934119780cb04 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); + 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); + + 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); + + 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, index); + charPos = index; + + 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); + + // 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); - 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); + final_merge->init_req(merge_index + 2, __ IfFalse(iff)); + final_mem->init_req(merge_index + 2, kit.memory(byte_adr_idx)); - 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.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(merge_index + 1, kit.control()); + final_mem->init_req(merge_index + 1, st); + } +} - Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR), - ch, T_CHAR, char_adr_idx, MemNode::unordered); +// 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)); + + // 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)); + } - 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); + 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); + } - head->init_req(2, ne); - mem->init_req(2, st); - i_phi->init_req(2, q); - charPos->init_req(2, m1); + // Final merge point for Latin1 and UTF16 case + kit.set_control(final_merge); + kit.set_memory(final_mem, byte_adr_idx); - charPos = m1; + C->record_for_igvn(final_merge); + C->record_for_igvn(final_mem); + return end; +} - kit.set_control(eq); - kit.set_memory(st, char_adr_idx); +// 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"); - C->record_for_igvn(head); - C->record_for_igvn(mem); - C->record_for_igvn(i_phi); - C->record_for_igvn(charPos); + if (elembt == T_CHAR) { + // Get number of chars + count = __ RShiftI(count, __ intcon(1)); } - { - // 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); - - final_merge->init_req(2, __ IfFalse(iff)); - final_mem->init_req(2, kit.memory(char_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); + 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); +} - final_merge->init_req(1, kit.control()); - final_mem->init_req(1, st); +#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(); + } +} - kit.set_control(final_merge); - kit.set_memory(final_mem, char_adr_idx); +// 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); +} - C->record_for_igvn(final_merge); - C->record_for_igvn(final_mem); +// 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(); -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); + 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); - } - return start; + 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(); + } + } + + // 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); - } - - // 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); + // Allocate destination byte array according to coder + dst_array = allocate_byte_array(kit, NULL, __ LShiftI(length, coder)); - // 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 0fb1ed70f64da747adb75b1eb020d9f5282c1573..d50616b33297b96f587ebf1193222da38bdeef90 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 1b37e0adceef4041d1dfb6dfb9bd389989f0f61a..ba6e8192746b4d076a9d1c0225fe84b9c21fe6a4 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/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 5bf88ead01706be9b567a16174f6968549bfe1c9..2c577ad9ed3a4ab939847a9204cee7c6dc5fef63 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(); @@ -3877,11 +3902,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()); @@ -3922,6 +3949,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 +4091,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 526eff57099e1f12125cdc50cea43f4791dc90f7..d88390504115424ad283e850d3ea0b438748dcba 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 c4e5b4e4a41423fab412a4cc1a5c20d8bc5264f3..d25485c051e60a9b42b0cd7c76f61bc101670846 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 53b5850712e1bc99b7f805117c5e5239977ecea4..c48de41227b0d8507584973134d6202c9481ac1d 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 b0c5a4325d9df8baa76adf7fa11afe50fb87dd6a..0dfdec9532cad041d222e2e34fdf616239b14437 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 09cc129fd7cc98b1917f6668604b913e4f38506f..6842d797b2333928a746b3ac4cddf12de74ce10d 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(</xsl:text> <xsl:value-of select="@num"/> <xsl:text>); - 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(</xsl:text> <xsl:value-of select="@num"/> diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index 2738581e042bf39709d19ded604ee8cc5c1b90db..f048ff17f630290e8cc08911546a7efe4b90dd25 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 db0437ab119c81dfad2c4818bc8c2e0aae6dc35d..e8327c2e0ea451c9e0eb74e071ab376572bd2ea8 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/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index b55e6e6d9a3229f8fee94da40fd8015c8631fddd..d05813da6a869f74d0f61f63c9f597e2e5697c53 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 d8dd5cea40e9fdfce6a3eecbdae169a3c543ec9f..b4c0cc6369430e0dc2c9044f9192633df22e94ac 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 ecc28a28d32b032ada3d615d7552ac1d435b0388..a468a62e5717454c1e2ce984c14ed2eabc83e4cf 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 05b5abb83a89fd6e8024924a55ff4f70fdb34ba2..0f58dde706394b3c30c2993bf3f262bc3c05c65b 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 41eff71f8f62f652a2fde827dfaffe1378ff9014..fecef0a50555582d9062141b3cbca35c1b1fb017 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 c7ffeb3cda33f22d7c7ab7fd57075beb96ec5626..d1cfcb9259a46e042e0d2e08581bb5c88ba99260 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 2d4492586600ad206e5bd075fff5faff102d48c7..d2d1f0bb8667dda5e3ef2c1613af067330074daf 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 dfd715a5f12ff9813fc0b0ea1d31d6a242a60cf5..0a626baca5c7241ec1295848d9e30f11dfb7cf92 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -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 <typename T> diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp index eb58e37c482468bbf463e82403f27c84dd8ae4fc..cd73fa78559f0283abb8c5c4775040adaacc8765 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 5ec406388f34afd6c2dfbfa37c463555f61c8515..2ae2ce9e15121b800993dbb15c3ea05841815be2 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 a35a00bb2dd705f05c6fce7c59f6e53688fa0bb0..e313c6255b3768420c5d48466280bce38292be8c 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1120,7 +1120,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 +1156,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 +1169,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 +2479,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 +3481,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 +3833,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/compilationPolicy.cpp b/hotspot/src/share/vm/runtime/compilationPolicy.cpp index 09d07a01d64415846c5601bf80ab5e0c52f0b039..d6c45d1247f239d5d38987c24d32ec345912795a 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<RFrame*>* 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 62df7ece209025a1d07a114af85c4481f02c1cdc..054671a846daaeae66d60be9b3af57366fb1f671 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<RFrame*>* 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 a79acbcede794cf10887249e7e8ff62b8ca805c0..ea868d4436857a3939a81f62fefef823a3e5e714 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"); diff --git a/hotspot/src/share/vm/runtime/deoptimization.hpp b/hotspot/src/share/vm/runtime/deoptimization.hpp index e02836849b6f6529c3d3a0a1a46e82e20b551ec5..b61c3506668d8d8464e373d8afe02ed1c1163a5d 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 0b208d249d921f38cb44adc7af75f245b3ece2a9..cbd63cd20b29472e175fe00e15d19d85ac394722 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 3357fcfc32386490a2320d8c674195bcd1d4d6aa..b41d13f1a2590d1274b790e33866d3e12624c93d 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); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 169316cd77ed80195c94821bb9dea7a535ba9ace..2ab6571046edd0f4401d471313bef2db9d9c803e 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 @@ -804,7 +812,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") \ @@ -1622,12 +1630,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 +1824,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 +1838,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") \ @@ -2080,10 +2075,6 @@ public: "unloading of classes when class unloading is enabled") \ range(0, 100) \ \ - develop(bool, CMSTestInFreeList, false, \ - "Check if the coalesced range is already in the " \ - "free lists as claimed") \ - \ notproduct(bool, CMSVerifyReturnedBytes, false, \ "Check that all the garbage collected was returned to the " \ "free lists") \ @@ -2889,6 +2880,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; " \ @@ -4253,7 +4247,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 08e04e414708f3dd2fbe46380a39480a4e214686..98ff1ffc4242d3de77d4698dca262623ae033395 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 d1d3d34adf797d8460c1a11285ef8999bc2c2389..35bb7684be89468814d69a5a73e06afa4ca967b7 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 c94e9d24f6a618b51114d2fe105114d01691e262..9acd0200b295fe488543a93ea668b4478e20d436 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 9ac2c9a5ea48472955252bbb8d55b4f8bcf48314..543e58f0dde2b5c1a2e518cc44b7079e3fb603f3 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 32e4b0942fb0880baac07a62560428757278662b..8cc40bc89dcbca94afa2562ae232859af6a30e35 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -96,8 +96,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 +157,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, @@ -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 8cca98661c2e974a5ffe5c83fbf28591b8ffbc62..0fc4770d432f23b2dfa90e65681825a6ce344861 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 @@ -722,7 +722,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 504cb1a8524ac5f1a9bb223618881d7e322f4c35..27d97bccd7598e16c01ec500189dadaae656a9b6 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 7e3c14b56a69a1357d5478ac34fabe727452add1..45746d67c7c2a835dcee1518389579a383f3a85c 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 <clinit> 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 593ff7ecc498b6e3ca4522a234dd737dbe0b0429..c73d0b9dfb321ad5e0d2b24de709e73a3fe5ae76 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 73b1ce3eed4a6e04cfaeda4982643169b791c2d8..e6ad4d1bfc774328f68744e4fe09c0b43b3dcd1d 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 6ea9ab4c8197b8456651211bdee4d324697f814d..3b5e5f70d5dbc756fa42894bc935f6eb7db57d1e 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 37d23b4c97c38391f2606167772de9d34a6e4291..5b89b8245eba744fd74b767074667328ee69037d 100644 --- a/hotspot/src/share/vm/runtime/safepoint.cpp +++ b/hotspot/src/share/vm/runtime/safepoint.cpp @@ -122,7 +122,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 @@ -901,7 +901,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; diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 231be768edf62b2a3a6b4fa2c913f9b292e388bf..b50160fc0130893e5babf9835f629a47d3d14ec8 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1142,7 +1142,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 +1697,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 +2430,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 +2640,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 65db7ad38e708c372a03106f05737b5f0a5b4f4b..1938c9dbb23f2af9caa780573354dc67ed8581d6 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 d1b2e04b1c346fee6cc7bf4719a293e954366d51..46e36e9f5324e74b55fa97405322f0e38dd94dca 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 4b17ca2bc8545db9dd9fb96d48a9f394178f6945..db3c1cc1089fff876e056bce877c4e5f9143dd24 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 87d009e136035b54a73760deb481dc799be77134..02a13cadc3c8fea2e3dc2e079388a8b66c830876 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 05b37c4808465806446e365d4a88c50a35bc0ced..fc7b2d72e84170357ce1ab01aaefe4a7a1c0d725 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 fec10fd757b1965e367e92fe7a5e28bea3897449..7046016299f709efdbb0a76ba29a9a9117c502e7 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<ObjectMonitor> *, 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<ObjectMonitor> * block = (PaddedEnd<ObjectMonitor> *)gBlockList; - ObjectMonitor* mid; - while (block) { + PaddedEnd<ObjectMonitor> * block = + (PaddedEnd<ObjectMonitor> *)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<ObjectMonitor> *) block->FreeNext; + block = (PaddedEnd<ObjectMonitor> *)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<ObjectMonitor> * block = - (PaddedEnd<ObjectMonitor> *)gBlockList; block != NULL; - block = (PaddedEnd<ObjectMonitor> *)next(block)) { + PaddedEnd<ObjectMonitor> * block = + (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList); + for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)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<ObjectMonitor> * block = - (PaddedEnd<ObjectMonitor> *)gBlockList; block != NULL; - block = (PaddedEnd<ObjectMonitor> *)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); + } else { + PaddedEnd<ObjectMonitor> * block = + (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList); + for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)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 (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<ObjectMonitor> * block = (PaddedEnd<ObjectMonitor> *)gBlockList; - ObjectMonitor* mid; - while (block) { + PaddedEnd<ObjectMonitor> * block = + (PaddedEnd<ObjectMonitor> *)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<ObjectMonitor> *) block->FreeNext; + block = (PaddedEnd<ObjectMonitor> *)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<ObjectMonitor> * block = (PaddedEnd<ObjectMonitor> *)gBlockList; - - while (block) { + PaddedEnd<ObjectMonitor> * block = + (PaddedEnd<ObjectMonitor> *)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<ObjectMonitor>)) == 0, "check"); + assert((diff % sizeof(PaddedEnd<ObjectMonitor>)) == 0, "must be aligned"); return 1; } - block = (PaddedEnd<ObjectMonitor> *) block->FreeNext; + block = (PaddedEnd<ObjectMonitor> *)block->FreeNext; } return 0; } diff --git a/hotspot/src/share/vm/runtime/synchronizer.hpp b/hotspot/src/share/vm/runtime/synchronizer.hpp index b08bd1bad1916aa72e27a27e71b41794ef6462e3..0d577bf3303edf6311b71bf01493e8ac97f30375 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<ObjectMonitor> *, 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/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 1fa6e2a7325f4b1f0b2157a2eb3b6e5142291427..633492be30bb3019dd10d5cdf3388e6452309b66 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -2101,7 +2101,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 +2219,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 +2933,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 +2948,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 +3296,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 +3625,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/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index ee9a24d6900a347c16e227d0b8eb4aec036a4515..3f39dcf13fe7e3e43ab354f231cd65fcdcfa03b4 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -278,6 +278,7 @@ typedef CompactHashtable<Symbol*, char> 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<Symbol*, char> 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) \ \ /*************/ \ @@ -1178,7 +1179,7 @@ typedef CompactHashtable<Symbol*, char> 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) */ \ @@ -2897,6 +2898,11 @@ typedef CompactHashtable<Symbol*, char> 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<Symbol*, char> 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/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index 1525188d1a780a6a51547805645e6736bac39498..24c76e5d172ecb6e0785746c47122a132cb9cc02 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 937d909b6f4f374c0a042f8de32619caaa6888a4..44ef64ce927cb17e15679daa16385bf3eef3f503 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,9 +895,7 @@ 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()) { @@ -939,10 +937,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 +1124,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 +1246,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 +1394,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 +1551,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 +1848,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 +1885,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()); } diff --git a/hotspot/src/share/vm/services/serviceUtil.hpp b/hotspot/src/share/vm/services/serviceUtil.hpp index 42e03d9df537d1de1fb54a0824322f428a4e6ac1..fca509770c21ea8b6983b5f1854e17b45ba73548 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 0551deff70c360cd1bca1260713db53f25e3ed8b..d0598e461959efaf3a1efd58c7e3ff51499ca2bc 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 f5c5121d80c804709657a58752ec4a85ea71117f..46bc012f73ed7fa967731ee0c763252ca77dbba2 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 4dda4b3e981075bd9b50a203bd248809849a8bc4..3541fddaecede5dda774b1ab50435119632978df 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 e3188ce8fa918351059cf07ef981c95daf6312be..78c9335d2286cd8d2fa4b14eacd37e5ddd90774f 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 0013e376c5ed95930d973a4498ce70019667cfe3..7c4179371d13ce40c334c12db4a051136440fb2f 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 9ad91c96d79e9a9c0fdfff38dd65259a603cdd27..51b813f4b8dee5554e4cfdfd8752d7dd6c5b0f31 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 0d5a12debb76decdb09492dfca0434870f9b5471..ef14a9ff121948a59d8b88edcfeb43496d6e88cd 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 6575090f1f4b59b25c8fce83e99b7ca6bb2da0d4..02d9110ef74cd131e5abc0c0a96d434fb51d59b0 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 5324d987f0930ccfe7109825ebe1990bbb1a439d..836e25b4f89a5de81198154f97f10c957bd01b93 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/utf8.cpp b/hotspot/src/share/vm/utilities/utf8.cpp index a0fbd95988e49c656cbb18a6a4a628f6b85c6442..d7a6043097a1aab4455d8562e8703856fb177508 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<typename T> 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<typename T> 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<jchar>(const char* str, jchar* value); +template char* UTF8::next<jbyte>(const char* str, jbyte* value); +template void UTF8::convert_to_unicode<jchar>(const char* utf8_str, jchar* unicode_str, int unicode_length); +template void UTF8::convert_to_unicode<jbyte>(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<typename T> +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<typename T> +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>(jbyte* base, int length); +template int UNICODE::quoted_ascii_length<jchar>(jchar* base, int length); +template void UNICODE::as_quoted_ascii<jbyte>(const jbyte* base, int length, char* buf, int buflen); +template void UNICODE::as_quoted_ascii<jchar>(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 354941e6dc0ec0eb6fe3df737e1b4ab7a425971a..161eb410f40d4a28926f6055df79945d08b66888 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<typename T> 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<typename T> 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<typename T> 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<typename T> 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 394c063e8b407e3b91b5f7668a874b5413c860d3..c5b90dee603d8bde215f31af0e0deb27326666fb 100644 --- a/hotspot/src/share/vm/utilities/xmlstream.cpp +++ b/hotspot/src/share/vm/utilities/xmlstream.cpp @@ -340,6 +340,7 @@ 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 // ------------------------------------------------------------------ diff --git a/hotspot/test/Makefile b/hotspot/test/Makefile index c3aa134d84c5b37556fe54e04c387ba45076ed29..41538dec380a848bf75dedcd73085fc9533eda50 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/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java index ab2177890074d7ed84505cbfe0a4b02f22926d60..91329b1b29c2df68bb545fa35692120a16984bf9 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 ea7689c7fc7ed3ab818981c9b763caeb05911072..bddbe6f4e3ece1a6b885244db703c20c48219e0c 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 0ec10ba45d328f198234be63389eaffc5b005cd8..9715b1e4662c9efa1fe0e2172d7aebd5414aa6de 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/intrinsics/string/TestStringIntrinsics.java b/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics.java new file mode 100644 index 0000000000000000000000000000000000000000..9fe60b51d8dca33ced05bde05ea9c13c74c147dc --- /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 12af053737b9e4400555a64b4db14436e3cd07b3..c9c0fc7506f411cf71c3face012cb6ab2b6e8883 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 c6e40a8cb9db3ed62550a8bd341fa1083a314910..33b29994149a25494285b329497988546562e6a1 100644 --- a/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java +++ b/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java @@ -27,32 +27,41 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" * @library /testlibrary /../../test/lib / - * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * @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::<cinit> provokes CompilerToVM::<init> + 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 02fa6b1cf19ab72251b86af29a05d0fd63085cac..2563b35e5a51b6f6c7bbe1a03c2a94b42f7a5b7a 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 2e12233a4861ea5be3781cf64352eedc3638b0d4..b5f4574b3a038e3b8ca58d46a7077260736b694d 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 9b80bf809d50ddc581f780cd37e4b0908f2e293b..35cece6db077f85fe0c894baa77fb8a4bcc1fae6 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/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/AbstractAddress.java b/hotspot/test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java similarity index 80% rename from hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/AbstractAddress.java rename to hotspot/test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java index 5b14cfc8c52f79d9a2cbca54235f7d32dc0417b4..4a49d01aca4b3c6cf7524ec55179c0bbb2d1c310 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/AbstractAddress.java +++ b/hotspot/test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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,10 +20,10 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.vm.ci.code; + +package jdk.vm.ci.hotspot; /** - * Abstract base class that represents a platform specific address. + * A public available version of MetaspaceWrapperObject interface. */ -public abstract class AbstractAddress { -} +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 eb09de4fdc075a3daea9b620a5af580282e5c398..0e97f5e601929af534a4737d15a1454ce9ae58b8 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java @@ -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<? extends Throwable> 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 9b164dade4e864e48c04f3030d9e56031c396701..06edb1a7d0123aa8dedaabe6b7e53ecd377a767f 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java @@ -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/CompileCodeTestCase.java b/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java index 00be80ea3ab26f00ab752d9f5cbd7338f3fb2df8..fa6483cf44986d45ca46d8a11685ef5e59435d2a 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<Class<?>, 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<Class<?>, 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<Object, ? extends Throwable> 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<CompileCodeTestCase> generate(int bci) { ArrayList<CompileCodeTestCase> 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 9f5409e551d722b090f22c6b58a87542928d3eb9..b9716cca2a2e1bb5b18630c20aa645153eb6357e 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<ConstantPoolTestsHelper.ConstantTypes, Validator> 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<ConstantPoolTestsHelper.ConstantTypes, Validator> typeTests) { + public ConstantPoolTestCase(Map<ConstantPoolTestsHelper.ConstantTypes,Validator> 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/DisassembleCodeBlobTest.java b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java index 10ab70bc5d2611ccabeac6132f851a7285750f82..ccebbff6a3235101973c8f5fef823c2a7fe0afee 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java @@ -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 b3f513c73de597a041631a47b54487d8526575c0..091e8ee14f7103f69cd9e8d52c5301ca84687f15 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java @@ -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 6e64d0793700d53eec59ecac869b69f16f06f8a0..2cb3df5fcdaa7e0c442019d7fd5756e622485118 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; @@ -35,7 +36,6 @@ import java.util.Map; public class ExecuteInstalledCodeTest { - public static void main(String[] args) { ExecuteInstalledCodeTest test = new ExecuteInstalledCodeTest(); List<CompileCodeTestCase> testCases = new ArrayList<>(); @@ -54,15 +54,14 @@ public class ExecuteInstalledCodeTest { // to have a clean state testCase.deoptimize(); Pair<Object, ? extends Throwable> 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<Object, ? extends Throwable> 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<Class<?>, 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 15ae1b74212605dee61fc875df19535976937ba2..2b3336cb115e591c4f859ad2b46f40d51b2ad0c1 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java @@ -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 b3c1600258075f58410a405256e4d0f209610087..29cbb0bfb687f8c8802b625d59c3443a0caf1ff3 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java @@ -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 6525b115dddffd6388d64e46194efe2935b76bb8..bd12d40504272f6c6c10849f8cd2ab407a7d3891 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java @@ -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 68185a9b06bdd2a4e59f06bfd879d23c19290cdf..552f63786ea4c6f98c57d2c785bea70efef925f1 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java @@ -27,12 +27,13 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" * @library /testlibrary /../../test/lib / - * @compile ../common/CompilerToVMHelper.java + * @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 9d928d3d0454104b7f87c58175bb1c190f2d10d1..fb2cf1410190a929ca199639c51a75fee417f3b7 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java @@ -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 aab452fd58a5bb7631c2c9cb72b9f9deeec2386d..c7ea597e5c8fc0437a5c4c7972562f50f493c704 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java @@ -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 1b3dcdcd60ddac0363e702f1ec5cbf27d04b7fd2..cf44fdad3d0851c6b11fe80e2f78d2cc43c2bfda 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java @@ -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 9bdb8525414e00da40d530cb453d68a9bc8210ad..3e5f0bfee0c2fd086029c03493bdd91bff6a58f6 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.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/GetNextStackFrameTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java index 4a7e3fa7adb3ac659156b80af746606ad11560f7..9665891c5674beed80bf04b6cc8e85155ddb548f 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java @@ -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 db8d0c6fc253dd57ed0acfe6b81a5a8c2f7afb89..d01aaffd0428f7e9ea35d4d1f19ca767c15827a8 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java @@ -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 e1d22fae3ced954a1a0b1e7d463099357536faa0..8cc9edf79e051f0b877863011338bee0692cd3ce 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java @@ -27,11 +27,13 @@ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" * @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 cc5f6bfff2548ddd2c5f4035ec29866072a12131..07818b4b213070925b22a68b82b5fe46af3f33af 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java @@ -27,11 +27,13 @@ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" * @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 389fb66a6a23d1bdb0bd29cfb1b3865e5985a3fc..83afe99b49c539e7cf272bee130ca6729a19bd42 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java @@ -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 2a2d26643501350a06c490e94a8c1b8a165254bb..cd6aba95ae4626e0448f50af9c95a28437359181 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java @@ -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<String> symbols; try { @@ -101,7 +101,7 @@ public class GetSymbolTest { } } - private List<String> getSymbols(HotSpotResolvedJavaMethodImpl + private List<String> getSymbols(HotSpotResolvedJavaMethod metaspaceMethod) throws ReflectiveOperationException { List<String> 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 682b9a0fa86b2314a7e31bdc94f2f978e111ac73..ba43e95bf4c397fe795d0b6d01b045a40ba83637 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java @@ -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 7db6ef081410c9513074368b45eadf9e39753ee5..e75230d6947b65a7dae4198f56f9adcb3f17b94e 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java @@ -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) { - List<CompileCodeTestCase>testCases = createTestCases(); + List<CompileCodeTestCase> 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 4a52691a9be2f59fa2e8e06e31dc69c812bde219..620ed814342248d15bd60af9b9c8a85e9a5b0303 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java @@ -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 0655d4c1d4372821ba1fe6098b33fa9bdceeb2e1..35fe8d189806b62c1afab45b84cfbe8233333492 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<TestCase> 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 1db21f10718c684e178b95d74cbcc88c3d929b80..c0ac4f58b8bf8d5dc3ed0fb584c1586b28036210 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java @@ -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("<null>"); - 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/JVM_RegisterJVMCINatives.java b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java index ddbc028be0a073b650693b47186b6cf262919448..00378a00ed75d4014c9d2583715e517afbd224b6 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 1db92682d4382c41aaf0319f8fbccefd3037f07c..521bd00c9b4b53f81d52bc05d793ab227786f61b 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java @@ -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 50142e50e697f9027347ee467c5b08b29171be1a..571bf15966040be6ee6f761d0c9169f0714de19e 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 2f63fcdc0ba64dcb8180f9899eead2bb9ac03dce..15a9a473b9dba81d0b136c2dd8a3a39d6b6c2cd6 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java @@ -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 746d5ee910095c0373486412eedb77e628a94102..05e5d47ffbc5065db7e9d494439eeccb794de747 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java @@ -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/ReprofileTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java index 24fa5b589b9d9cad29306c59b03b2bc4e6940f0d..0f7c1892918d004a39d5db90b6ebc41fc3a5cec3 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java @@ -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 ffbecca7dbff019d17183c367e1faf622d52a02e..0a8070d158e4a993c0a4e694bbac93ef2177fd6e 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java @@ -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 8881d7a9f9f0dc5f52c8f0a7db1a5a48aaac8149..403d4007b1266ef8c259b25eb48d14966b7a78de 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java @@ -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 3a98e76282c4cecdbde550e65eb5af4caf8ed375..bd0e2ec35f6b35cdd062b493092d76fb7f155a56 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java @@ -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/ShouldInlineMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java index e709449a8be387dbd0ac28fff719e5e923566ad5..c1a591477f4e6e29b4bc8a92ed0c0d3d2ea75ec2 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java @@ -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 f9f1333a238dd33d2d23a797f5efa79ebbf26d83..0000000000000000000000000000000000000000 --- 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 742878c0dfaca3fcf98d59e188e5cafd57478cfb..0000000000000000000000000000000000000000 --- 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 82591452d8c63b494c5df45b39b7a4dd7ef31704..7ad73d879123275d6a5228f4a5a931f942171664 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 a9648ea676e6a0779f46c76c5136d7e2ce848856..552a9937574945fc12be577397d48de25a668449 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 17135e43e942bf6beeeb314599329bd08f707027..b9872d76fdd889e0b2fcffb887b90c2dc59cb9d7 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 3aebfec6189e17fbbd459516c3aae909b77e59f6..ab214fd66ad83fc5c618a2c812435cfa490bb3ca 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 72f64ade9180d4904ed70c24fed8182c826aae84..e8d325024a0582a0825ae29975b1388bbfb6215c 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 f7f59e82c54c57845f0030e11cfe252dca7663b8..35368ebeca414fdbd2df28f9f5fbce304f042f06 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 95341f347f350f5ea6a236fe2cd89e06d641c432..d7fc033158e66e38f1faa6a41e31a908eb77471d 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 84def0f2c7751231a581be07c4a0744c18b63651..f7422fbce784285285c1bef51d1a5b3a8289d319 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 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 javax.tools.*; - -import jdk.vm.ci.meta.*; - -import org.junit.*; +import static org.junit.Assume.assumeTrue; + +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.ToolProvider; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +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 6e7db7c08cc77f509a6a88694370decb1923bad8..f6d38b44bbd02127514e7fa12997f3e3c289ee8e 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 org.junit.*; +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.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 580c353da90a6a809f97aa0b1c954438f27ba03c..2b5d05c60d501aba80ff7f294a331fd4acdf0a54 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 org.junit.*; +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.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 7d5c265ef5e54cd93092369179eef8333dd6abb7..bdb258038b8161c0da60121eecd7d18089c6f60d 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 f0a6c7d36574d3b21b35200b2185277065934c61..1dea56cc20a268be62a630382f5d6ac86acebb9d 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 185bc29fcd127bbb2187b6ba329c4c6b44439d69..f5e5b368e3e3fce7e56340df2402f551dba7464b 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 62a13a24292cab3b09317313a5fef76dec92bd01..e17427bf432637c1e4f35aa769dcf7b6c8a01043 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 968066d59db63749b46aa8b43b5c174a43c27eec..c0420f4f5e40767a2890c24ca2b3567b5b48f1e3 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 88b3b5f9751392ff1d1a14f172e55379250a334d..4b0c4df2c74b571335f0e0c62434fd4297a0cea4 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 java.lang.annotation.*; -import java.lang.reflect.*; -import java.util.*; - -import jdk.vm.ci.meta.*; - -import org.junit.*; +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.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.JavaConstant; +import jdk.vm.ci.meta.LocationIdentity; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +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 2b0f7b4aab402f779f31a4480d768d87d1af23e4..39ef621f9245cceddf61fcffd44c3b8f48a2de9b 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 java.lang.annotation.*; -import java.lang.invoke.*; -import java.lang.reflect.*; -import java.util.*; - -import jdk.vm.ci.meta.*; - -import org.junit.*; +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.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.ConstantPool; +import jdk.vm.ci.meta.ExceptionHandler; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; + +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 42520f7d8ea450dae7bcff199befc6fb199f5423..2ddf7797fcc8c56601d45f2d1b3540783549190e 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 java.lang.annotation.*; -import java.lang.reflect.*; -import java.net.*; -import java.util.*; - -import jdk.vm.ci.common.*; -import jdk.vm.ci.meta.*; -import jdk.vm.ci.meta.Assumptions.*; - -import org.junit.*; +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.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.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.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 0cb74ed83f4476a695e26775c4ace0596887c6c9..f2a187effa89ca2178cfbdce3ab65efbf4802912 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 java.io.*; -import java.lang.reflect.*; -import java.util.*; +import static java.lang.reflect.Modifier.isFinal; +import static java.lang.reflect.Modifier.isStatic; + +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 f4f2826b6e4dab97a1d78b68d84ac94ffc31c984..bef045701ec4c268cc71c3a709ef513af6ced138 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/unsafe/UnsafeGetConstantField.java b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java index 110c9dfb22c0be049c315fc481dcbc73f3dd8e18..12e7c5653248b1bd4b7c3d6d0b835a79fd6ef70d 100644 --- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java +++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java @@ -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/gc/g1/TestGCLogMessages.java b/hotspot/test/gc/g1/TestGCLogMessages.java index 380d89a46a91bc2bdec838c3e574cd27c68c52b6..ec5b87d30814f3c2679495500e6d1e8dd67a8f61 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/runtime/Annotations/TestAnnotatedStringEncoding.java b/hotspot/test/runtime/Annotations/TestAnnotatedStringEncoding.java new file mode 100644 index 0000000000000000000000000000000000000000..ed89c00fea42a8ad3ca6234239d016e3b01e982a --- /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/CommandLine/IgnoreUnrecognizedVMOptions.java b/hotspot/test/runtime/CommandLine/IgnoreUnrecognizedVMOptions.java new file mode 100644 index 0000000000000000000000000000000000000000..c876b136969652afda60a361f19de8b78f5f5cf1 --- /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 38b3239eb14bbe87b6ca01c644c8d76d1b7e59fb..fa9ad87eb5295a2a1c0f2b56497ed05c3d4a7deb 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 d0f9e0b0819c7f7cd4fc30d997f29cd991e7cc89..7158b356eed8b2fad007e2ae20156b786662d531 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/SharedArchiveFile/CdsDifferentCompactStrings.java b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java new file mode 100644 index 0000000000000000000000000000000000000000..3f8669241c04a0c1a718e683f86e2b09ae161a10 --- /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/testlibrary/jdk/test/lib/Utils.java b/hotspot/test/testlibrary/jdk/test/lib/Utils.java index 535127cad7b4729ec5782c9fe603511e9a5d3e75..6776db006fe3432a52baaf453aae73a934dfa95d 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<Class<?>, 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/jaxp/.hgtags b/jaxp/.hgtags index a1e0320a6bfe55fafea7cb552fd86779de38246c..ac30f3e5525487e3f22210c154377d740b792cff 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -334,3 +334,4 @@ eb435c878c2cbbfb043d0b205f4d5bd6faffd44a jdk9-b87 5021da4c949690e5c2578c073c36fb161e4b35e5 jdk9-b89 35f68242b624112cb6ef7e6226059674d6b499f4 jdk9-b90 ffaff3d0ad0e0ca1e632b80826afa8729ee72a48 jdk9-b91 +fcabfb3c38ac1da99394e821902537d92e45222d jdk9-b92 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 abb5b3cffc19fc21413c165c0de773e888bba3a1..4718d34cae6270828dbce1738e565593ab22c586 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/jaxws/.hgtags b/jaxws/.hgtags index 9633753382956a3f736d3dd2bcf85cee2a9e39f3..2d9f1ee7a3ef48bae21a0f3a94e0035de421ae53 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -337,3 +337,4 @@ f6425fec60abe3c096c5251be61e4621c817be80 jdk9-b88 2d84c6f4cbbac5871b099e97f8f968d9de6b52bc jdk9-b89 b3e45213d574618f6520fa6978e4a14ba577c2db jdk9-b90 3b2a3cb658e41618bd152a7598d12e1f0c10e8f7 jdk9-b91 +fe772cbc64f4e0418c5bf694e9e7123f02e1808f jdk9-b92 diff --git a/jdk/.hgtags b/jdk/.hgtags index db3016620bf53d0b6a7bc32362c97e157695670e..4f2107c42121a619d578d68720d4f1817633625a 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -334,3 +334,4 @@ e8a66c0b05d786a282a7ff1d7eb4989afa30c891 jdk9-b86 0d0a63b325592607974612f9cfb48590975aa2d6 jdk9-b89 b433e4dfb830fea60e5187e4580791b62cc362d2 jdk9-b90 97624df5026a2fb191793697dbd2c604c4d5c66e jdk9-b91 +6a5c99506f44538b879d8635a3979849ed587130 jdk9-b92 diff --git a/jdk/make/Import.gmk b/jdk/make/Import.gmk index ffe2869897f6cc6d4b0edcff6ddbc427a055bef7..25560f02ff05a8edd4ba69e3fdf715eae8b26a82 100644 --- a/jdk/make/Import.gmk +++ b/jdk/make/Import.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2014, 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 @@ -45,8 +45,16 @@ endif # # Import hotspot # + +# Don't import jsig library for static builds +ifneq ($(STATIC_BUILD), true) + JSIG_IMPORT = jsig.* +else + JSIG_IMPORT = +endif + HOTSPOT_BASE_IMPORT_FILES := \ - $(addprefix $(LIBRARY_PREFIX), jvm.* jsig.* jvm_db.* jvm_dtrace.*) \ + $(addprefix $(LIBRARY_PREFIX), jvm.* $(JSIG_IMPORT) jvm_db.* jvm_dtrace.*) \ Xusage.txt \ # @@ -79,32 +87,34 @@ SA_TARGETS := $(COPY_HOTSPOT_SA) ################################################################################ -ifeq ($(OPENJDK_TARGET_OS), macosx) - JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig$(SHARED_LIBRARY_SUFFIX).dSYM) \ - $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) ) -else - JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.debuginfo) \ - $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) ) -endif +ifneq ($(STATIC_BUILD), true) + ifeq ($(OPENJDK_TARGET_OS), macosx) + JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig$(SHARED_LIBRARY_SUFFIX).dSYM) \ + $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) ) + else + JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.debuginfo) \ + $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) ) + endif -ifneq ($(OPENJDK_TARGET_OS), windows) - ifeq ($(JVM_VARIANT_SERVER), true) - BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) - ifneq (, $(JSIG_DEBUGINFO)) - BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) + ifneq ($(OPENJDK_TARGET_OS), windows) + ifeq ($(JVM_VARIANT_SERVER), true) + BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) + ifneq (, $(JSIG_DEBUGINFO)) + BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) + endif endif - endif - ifeq ($(JVM_VARIANT_CLIENT), true) - BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) - ifneq (, $(JSIG_DEBUGINFO)) - BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) + ifeq ($(JVM_VARIANT_CLIENT), true) + BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) + ifneq (, $(JSIG_DEBUGINFO)) + BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) + endif endif - endif - ifneq ($(OPENJDK_TARGET_OS), macosx) - ifeq ($(JVM_VARIANT_MINIMAL1), true) - BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) - ifneq (,$(JSIG_DEBUGINFO)) - BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) + ifneq ($(OPENJDK_TARGET_OS), macosx) + ifeq ($(JVM_VARIANT_MINIMAL1), true) + BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) + ifneq (,$(JSIG_DEBUGINFO)) + BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) + endif endif endif endif diff --git a/jdk/make/data/charsetmapping/DoubleByte-X.java.template b/jdk/make/data/charsetmapping/DoubleByte-X.java.template index 4ef582c93172019444b247c4bfad67b3a69d3564..d97e2c46f4bfdcda382206b84ab3828d06ab1851 100644 --- a/jdk/make/data/charsetmapping/DoubleByte-X.java.template +++ b/jdk/make/data/charsetmapping/DoubleByte-X.java.template @@ -50,12 +50,12 @@ public class $NAME_CLZ$ extends Charset public CharsetDecoder newDecoder() { initb2c(); - return new DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$); + return new DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$, $ASCIICOMPATIBLE$); } public CharsetEncoder newEncoder() { initc2b(); - return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex); + return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex, $ASCIICOMPATIBLE$); } $B2C$ diff --git a/jdk/make/data/charsetmapping/SingleByte-X.java.template b/jdk/make/data/charsetmapping/SingleByte-X.java.template index 82af0521809ca3477961924effe2e8a640689103..2acb1ef256ddf9e6bf7b7dc15e121485cc978ef4 100644 --- a/jdk/make/data/charsetmapping/SingleByte-X.java.template +++ b/jdk/make/data/charsetmapping/SingleByte-X.java.template @@ -48,11 +48,11 @@ public class $NAME_CLZ$ extends Charset implements HistoricallyNamedCharset } public CharsetDecoder newDecoder() { - return new SingleByte.Decoder(this, b2c); + return new SingleByte.Decoder(this, b2c, $ASCIICOMPATIBLE$); } public CharsetEncoder newEncoder() { - return new SingleByte.Encoder(this, c2b, c2bIndex); + return new SingleByte.Encoder(this, c2b, c2bIndex, $ASCIICOMPATIBLE$); } private final static String b2cTable = $B2CTABLE$ diff --git a/jdk/make/gensrc/Gensrc-java.base.gmk b/jdk/make/gensrc/Gensrc-java.base.gmk index 134edea72b04d082f0eedb869e03f9163191a6e8..e176d88ea7e5832c2a54f922af8c52f817fba262 100644 --- a/jdk/make/gensrc/Gensrc-java.base.gmk +++ b/jdk/make/gensrc/Gensrc-java.base.gmk @@ -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 @@ -38,15 +38,15 @@ include GensrcExceptions.gmk include GensrcProperties.gmk -$(eval $(call SetupCompileProperties,LIST_RESOURCE_BUNDLE, \ - $(filter %.properties, \ - $(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources)), \ - ListResourceBundle)) +$(eval $(call SetupCompileProperties, LIST_RESOURCE_BUNDLE, \ + SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources, \ + CLASS := ListResourceBundle, \ +)) -$(eval $(call SetupCompileProperties,SUN_UTIL, \ - $(filter %.properties, \ - $(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources)), \ - sun.util.resources.LocaleNamesBundle)) +$(eval $(call SetupCompileProperties, SUN_UTIL, \ + SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources, \ + CLASS := sun.util.resources.LocaleNamesBundle, \ +)) GENSRC_JAVA_BASE += $(LIST_RESOURCE_BUNDLE) $(SUN_UTIL) diff --git a/jdk/make/gensrc/Gensrc-java.desktop.gmk b/jdk/make/gensrc/Gensrc-java.desktop.gmk index d22691503362ba8a5f0aa568733593a25e929c98..05e93c66e3fd93babc8277ac330f9664ba7a5bff 100644 --- a/jdk/make/gensrc/Gensrc-java.desktop.gmk +++ b/jdk/make/gensrc/Gensrc-java.desktop.gmk @@ -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 @@ -66,11 +66,11 @@ else PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources endif -PROP_SRC_FILES := $(filter-out %cursors.properties, \ - $(filter %.properties, $(call CacheFind, $(PROP_SRC_DIRS)))) - -$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ - $(PROP_SRC_FILES), ListResourceBundle)) +$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ + SRC_DIRS := $(PROP_SRC_DIRS), \ + EXCLUDE := %cursors.properties, \ + CLASS := ListResourceBundle, \ +)) GENSRC_JAVA_DESKTOP += $(COMPILE_PROPERTIES) diff --git a/jdk/make/gensrc/Gensrc-java.logging.gmk b/jdk/make/gensrc/Gensrc-java.logging.gmk index 18ad984f8597aaeb89ecc9da8db3993f51a5dfde..ea44f5701a615cedf0060e5f6832d1be84fa5cc9 100644 --- a/jdk/make/gensrc/Gensrc-java.logging.gmk +++ b/jdk/make/gensrc/Gensrc-java.logging.gmk @@ -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 @@ -29,10 +29,10 @@ include GensrcCommon.gmk include GensrcProperties.gmk -$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ - $(filter %.properties, \ - $(call CacheFind, $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources)), \ - ListResourceBundle)) +$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ + SRC_DIRS := $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources, \ + CLASS := ListResourceBundle, \ +)) TARGETS += $(COMPILE_PROPERTIES) diff --git a/jdk/make/gensrc/Gensrc-java.management.gmk b/jdk/make/gensrc/Gensrc-java.management.gmk index b0a3751631e399ff0316a992e0f5399ddff3de64..771392466fddc59f9a48029d95e0562533ac5d23 100644 --- a/jdk/make/gensrc/Gensrc-java.management.gmk +++ b/jdk/make/gensrc/Gensrc-java.management.gmk @@ -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 @@ -32,10 +32,10 @@ $(eval $(call IncludeCustomExtension, jdk, gensrc/Gensrc-java.management.gmk)) include GensrcProperties.gmk -$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ - $(filter %.properties, \ - $(call CacheFind, $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources)), \ - ListResourceBundle)) +$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ + SRC_DIRS := $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources, \ + CLASS := ListResourceBundle, \ +)) TARGETS += $(COMPILE_PROPERTIES) diff --git a/jdk/make/gensrc/Gensrc-jdk.dev.gmk b/jdk/make/gensrc/Gensrc-jdk.dev.gmk index b8f57aa529edb656a2d9eec978142d09de875555..4316c485883a13865d829ab164ceadc914da9c6b 100644 --- a/jdk/make/gensrc/Gensrc-jdk.dev.gmk +++ b/jdk/make/gensrc/Gensrc-jdk.dev.gmk @@ -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 @@ -29,11 +29,10 @@ include GensrcCommon.gmk include GensrcProperties.gmk -$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ - $(filter %.properties, \ - $(call CacheFind, \ - $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/tools/jimage/resources)), \ - ListResourceBundle)) +$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ + SRC_DIRS := $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/tools/jimage/resources, \ + CLASS := ListResourceBundle, \ +)) TARGETS += $(COMPILE_PROPERTIES) diff --git a/jdk/make/gensrc/Gensrc-jdk.jartool.gmk b/jdk/make/gensrc/Gensrc-jdk.jartool.gmk index 0fb8eabc621a3a2b3e6044014fbb53dce69792c8..8cb04f33f7f61f189df267fd9098925a59d40dbb 100644 --- a/jdk/make/gensrc/Gensrc-jdk.jartool.gmk +++ b/jdk/make/gensrc/Gensrc-jdk.jartool.gmk @@ -29,11 +29,10 @@ include GensrcCommon.gmk include GensrcProperties.gmk -$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ - $(filter %.properties, \ - $(call CacheFind, \ - $(JDK_TOPDIR)/src/jdk.jartool/share/classes/sun/tools/jar/resources)), \ - ListResourceBundle)) +$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ + SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jartool/share/classes/sun/tools/jar/resources, \ + CLASS := ListResourceBundle, \ +)) TARGETS += $(COMPILE_PROPERTIES) diff --git a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk index 7c36f4e699960ecdefe45eb65d126c90232db656..416ec40852b1cf0a022177381bdc60f9a1001fea 100644 --- a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk +++ b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk @@ -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 @@ -34,7 +34,7 @@ HEADER_FILE := $(SUPPORT_OUTPUTDIR)/headers/jdk.jdwp.agent/JDWPCommands.h JAVA_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/com/sun/tools/jdi/JDWP.java # Both the header and java file are created using the same recipe. By declaring -# this rule and adding header file to dependencies for java file, both are +# this rule and adding header file to dependencies for java file, both are # rebuilt if either is missing $(HEADER_FILE): $(JDWP_SPEC_FILE) $(BUILD_TOOLS_JDK) @@ -90,10 +90,10 @@ endif include GensrcProperties.gmk -$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ - $(filter %.properties, \ - $(call CacheFind, $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources)), \ - ListResourceBundle)) +$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ + SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources, \ + CLASS := ListResourceBundle, \ +)) GENSRC_JDK_JDI += $(COMPILE_PROPERTIES) diff --git a/jdk/make/gensrc/Gensrc-jdk.localedata.gmk b/jdk/make/gensrc/Gensrc-jdk.localedata.gmk index 5759cb6093d37bdc8999a5aaacc3ad1096c5decc..5bbe512dc18dbeeaa2bc2cfede50cdd010a7cb7e 100644 --- a/jdk/make/gensrc/Gensrc-jdk.localedata.gmk +++ b/jdk/make/gensrc/Gensrc-jdk.localedata.gmk @@ -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 @@ -35,10 +35,10 @@ include GensrcCLDR.gmk include GensrcProperties.gmk -$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ - $(filter %.properties, \ - $(call CacheFind, $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources)), \ - sun.util.resources.LocaleNamesBundle)) +$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ + SRC_DIRS := $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources, \ + CLASS := sun.util.resources.LocaleNamesBundle, \ +)) # Skip generating zh_HK from zh_TW for this module. GENSRC_JDK_LOCALEDATA += $(filter-out %_zh_HK.java, $(COMPILE_PROPERTIES)) diff --git a/jdk/make/gensrc/GensrcProperties.gmk b/jdk/make/gensrc/GensrcProperties.gmk index 220b8509904b598ea918fbcc14d02c2f5de98b18..7293a19bbebd474ff9b16b3c1cbd53bbb6cc87f7 100644 --- a/jdk/make/gensrc/GensrcProperties.gmk +++ b/jdk/make/gensrc/GensrcProperties.gmk @@ -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 @@ -49,30 +49,40 @@ define SetupCopy-zh_HK endef ################################################################################ -# Creates a rule that runs CompileProperties on a set of properties files. -# Param 1 - Variable to add targets to, must not contain space -# Param 2 - Properties files to process -# Param 3 - The super class for the generated classes -# Param 4 - Module path root, defaults to $(JDK_TOPDIR)/src -define SetupCompileProperties - $1_SRCS := $2 - $1_CLASS := $3 - $1_MODULE_PATH_ROOT := $4 - +# Setup make rules that runs CompileProperties on a set of properties files. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. +# +# Remaining parameters are named arguments. These include: +# SRC_DIRS Directories containing properties files to process. +# EXCLUDE Exclude files matching this pattern. +# CLASS The super class for the generated classes. +# MODULE_PATH_ROOT Module path root, defaults to $(JDK_TOPDIR)/src. +SetupCompileProperties = $(NamedParamsMacroTemplate) +define SetupCompilePropertiesBody + # Set default value unless overridden ifeq ($$($1_MODULE_PATH_ROOT), ) $1_MODULE_PATH_ROOT := $(JDK_TOPDIR)/src endif + # Locate all properties files in the given source dirs. + $1_SRC_FILES := $$(filter %.properties, $$(call CacheFind, $$($1_SRC_DIRS))) + + ifneq ($$($1_EXCLUDE), ) + $1_SRC_FILES := $$(filter-out $$($1_EXCLUDE), $$($1_SRC_FILES)) + endif + # Convert .../src/<module>/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties # to .../support/gensrc/<module>/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: # "<module>/share/classes/com/sun/tools/javac/resources/javac_zh_CN" $1_JAVAS := $$(patsubst $$($1_MODULE_PATH_ROOT)/%, \ $(SUPPORT_OUTPUTDIR)/gensrc/%, \ $$(patsubst %.properties, %.java, \ $$(subst /$(OPENJDK_TARGET_OS)/classes,, \ $$(subst /$(OPENJDK_TARGET_OS_TYPE)/classes,, \ - $$(subst /share/classes,, $$($1_SRCS)))))) + $$(subst /share/classes,, $$($1_SRC_FILES)))))) # Generate the package dirs for the to be generated java files. Sort to remove # duplicates. @@ -82,22 +92,22 @@ define SetupCompileProperties # "-compile ...javac_zh_CN.properties ...javac_zh_CN.java java.util.ListResourceBundle" # suitable to be fed into the CompileProperties command. $1_CMDLINE := $$(subst _SPACE_, $(SPACE), \ - $$(join $$(addprefix -compile_SPACE_, $$($1_SRCS)), \ + $$(join $$(addprefix -compile_SPACE_, $$($1_SRC_FILES)), \ $$(addsuffix _SPACE_$$($1_CLASS), \ $$(addprefix _SPACE_, $$($1_JAVAS))))) - $1_TARGET := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.done + $1_TARGET := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.marker $1_CMDLINE_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.cmdline # Now setup the rule for the generation of the resource bundles. - $$($1_TARGET): $$($1_SRCS) $$($1_JAVAS) $(BUILD_TOOLS_JDK) + $$($1_TARGET): $$($1_SRC_FILES) $$($1_JAVAS) $(BUILD_TOOLS_JDK) $(MKDIR) -p $$(@D) $$($1_DIRS) - $(ECHO) Compiling $$(words $$($1_SRCS)) properties into resource bundles for $(MODULE) + $(ECHO) Compiling $$(words $$($1_SRC_FILES)) properties into resource bundles for $(MODULE) $$(eval $$(call ListPathsSafely, $1_CMDLINE, $$($1_CMDLINE_FILE))) $(TOOL_COMPILEPROPERTIES) -quiet @$$($1_CMDLINE_FILE) $(TOUCH) $$@ - $$($1_JAVAS): $$($1_SRCS) + $$($1_JAVAS): $$($1_SRC_FILES) # Create zh_HK versions of all zh_TW files created above $$(eval $$(call SetupCopy-zh_HK,$1_HK,$$(filter %_zh_TW.java, $$($1_JAVAS)))) diff --git a/jdk/make/launcher/LauncherCommon.gmk b/jdk/make/launcher/LauncherCommon.gmk index 942224f4697634b1bb65dcf612bb933d0325adfb..debc6337b60bfad201c5b355034ef2f4bb94a7de 100644 --- a/jdk/make/launcher/LauncherCommon.gmk +++ b/jdk/make/launcher/LauncherCommon.gmk @@ -122,8 +122,23 @@ define SetupBuildLauncherBody endif $1_CFLAGS += -DPACKAGE_PATH='"$(PACKAGE_PATH)"' - $1_LDFLAGS += -Wl,-all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a \ + $1_LDFLAGS += -Wl,-all_load \ -sectcreate __TEXT __info_plist $(MACOSX_PLIST_DIR)/$$($1_PLIST_FILE) + ifeq ($(STATIC_BUILD), true) + $1_LDFLAGS += -exported_symbols_list \ + $(SUPPORT_OUTPUTDIR)/build-static/exported.symbols + $1_LIBS += \ + $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs/java.base -name "*.a") \ + $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/libdt_socket.a \ + $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/libjdwp.a \ + $(SUPPORT_OUTPUTDIR)/native/java.base/$(LIBRARY_PREFIX)fdlibm$(STATIC_LIBRARY_SUFFIX) \ + -framework CoreFoundation \ + -framework Foundation \ + -framework SystemConfiguration \ + -lstdc++ -liconv + else + $1_LIBS += $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a + endif $1_LIBS += -framework Cocoa -framework Security \ -framework ApplicationServices endif diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index ad60e8a814604ef6030baeed5625bb16ff167562..21e61c5c6797559b01cb3729d23295f1ebe36f87 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -476,7 +476,7 @@ endif ifeq ($(USE_EXTERNAL_LIBJPEG), true) LIBJPEG_LIBS := -ljpeg BUILD_LIBJAVAJPEG_INCLUDE_FILES := \ - imageIOJPEG.c \ + imageioJPEG.c \ jpegdecoder.c BUILD_LIBJAVAJPEG_HEADERS := else diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index 01ae7467e5d21065eeceb15fe469b67255c9c25b..9fe9305fcd77a357f846c06b371a001c87a1723b 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -435,10 +435,14 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx) OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static, \ DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) - $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a: $(BUILD_LIBJLI_STATIC) + ifeq ($(STATIC_BUILD), true) + TARGETS += $(BUILD_LIBJLI_STATIC) + else + $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a: $(BUILD_LIBJLI_STATIC) $(call install-file) - TARGETS += $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a + TARGETS += $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a + endif else ifeq ($(OPENJDK_TARGET_OS), aix) # AIX also requires a static libjli because the compiler doesn't support '-rpath' diff --git a/jdk/make/lib/Lib-java.base.gmk b/jdk/make/lib/Lib-java.base.gmk index c5949d5713846e8ab6c0e1f7a3ccb0e1c80e0cff..0699a42dd348a3d2743127e876400e6446e2e83d 100644 --- a/jdk/make/lib/Lib-java.base.gmk +++ b/jdk/make/lib/Lib-java.base.gmk @@ -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 @@ -33,3 +33,29 @@ include CoreLibraries.gmk include NetworkingLibraries.gmk include NioLibraries.gmk include SecurityLibraries.gmk + +ifeq ($(STATIC_BUILD), true) + JAVA_BASE_EXPORT_SYMBOLS_SRC := \ + $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jli/$(LIBRARY_PREFIX)jli.symbols \ + $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)java.symbols \ + $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)net.symbols \ + $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)nio.symbols \ + $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)verify.symbols \ + $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)zip.symbols \ + $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)jimage.symbols \ + $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/server/$(LIBRARY_PREFIX)jvm.symbols \ + # + + JAVA_BASE_EXPORT_SYMBOL_FILE := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/java.base.symbols + + $(JAVA_BASE_EXPORT_SYMBOL_FILE): $(JAVA_BASE_EXPORT_SYMBOLS_SRC) + $(ECHO) $(LOG_INFO) "Generating java.base.symbols file" + $(CAT) $^ > $@ + + # The individual symbol files is generated when the respective lib is built + $(JAVA_BASE_EXPORT_SYMBOLS_SRC): $(BUILD_LIBJLI) $(BUILD_LIBJAVA) \ + $(BUILD_LIBNET) $(BUILD_LIBNIO) $(BUILD_LIBVERIFY) $(BUILD_LIBZIP) \ + $(BUILD_LIBJIMAGE) + + TARGETS += $(JAVA_BASE_EXPORT_SYMBOL_FILE) +endif diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk index 504df6dd4d0987a686053ee63477b979e758b12a..14784d3796abbaf9d933bbc2c804e1e5edc4d966 100644 --- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk @@ -102,3 +102,23 @@ $(BUILD_LIBJDWP): $(call FindLib, java.base, java) TARGETS += $(BUILD_LIBJDWP) ################################################################################ + +ifeq ($(STATIC_BUILD), true) + JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC := \ + $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/$(LIBRARY_PREFIX)dt_socket.symbols \ + $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/$(LIBRARY_PREFIX)jdwp.symbols + + JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE := $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/jdk.jdwp.agent.symbols + + $(JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE): $(JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC) + $(ECHO) $(LOG_INFO) "Generating jdk.jdwp.agent symbols file" + $(CAT) $^ > $@ + + # The individual symbol files is generated when the respective lib is built + $(JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC): $(BUILD_LIBDT_SOCKET) $(BUILD_LIBJDWP) + + TARGETS += $(JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE) + +endif + +################################################################################ diff --git a/jdk/make/lib/SecurityLibraries.gmk b/jdk/make/lib/SecurityLibraries.gmk index a1c51b73ae34be0fe42873ba441cc28897dc2f2a..9c1c65211ca66f6b768f81532ae2bfbbfe521302 100644 --- a/jdk/make/lib/SecurityLibraries.gmk +++ b/jdk/make/lib/SecurityLibraries.gmk @@ -26,38 +26,41 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), macosx) + # JavaNativeFoundation framework not supported in static builds + ifneq ($(STATIC_BUILD), true) ################################################################################ - LIBOSXSECURITY_DIRS := $(JDK_TOPDIR)/src/java.base/macosx/native/libosxsecurity - LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - - $(eval $(call SetupNativeCompilation,BUILD_LIBOSXSECURITY, \ - LIBRARY := osxsecurity, \ - OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ - SRC := $(LIBOSXSECURITY_DIRS), \ - OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBOSXSECURITY_CFLAGS), \ - DISABLED_WARNINGS_clang := deprecated-declarations, \ - LDFLAGS := $(LDFLAGS_JDKLIB) \ - -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \ - $(call SET_SHARED_LIBRARY_ORIGIN) \ - -fobjc-link-runtime, \ - LIBS := \ - -framework JavaNativeFoundation \ - -framework CoreServices \ - -framework Security \ - $(JDKLIB_LIBS), \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxsecurity, \ - DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) - - $(BUILD_LIBOSXSECURITY): $(BUILD_LIBJAVA) - - TARGETS += $(BUILD_LIBOSXSECURITY) + LIBOSXSECURITY_DIRS := $(JDK_TOPDIR)/src/java.base/macosx/native/libosxsecurity + LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \ + $(LIBJAVA_HEADER_FLAGS) \ + -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ + + $(eval $(call SetupNativeCompilation,BUILD_LIBOSXSECURITY, \ + LIBRARY := osxsecurity, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + SRC := $(LIBOSXSECURITY_DIRS), \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CFLAGS_JDKLIB) \ + $(LIBOSXSECURITY_CFLAGS), \ + DISABLED_WARNINGS_clang := deprecated-declarations, \ + LDFLAGS := $(LDFLAGS_JDKLIB) \ + -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \ + $(call SET_SHARED_LIBRARY_ORIGIN) \ + -fobjc-link-runtime, \ + LIBS := \ + -framework JavaNativeFoundation \ + -framework CoreServices \ + -framework Security \ + $(JDKLIB_LIBS), \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxsecurity, \ + DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) + + $(BUILD_LIBOSXSECURITY): $(BUILD_LIBJAVA) + + TARGETS += $(BUILD_LIBOSXSECURITY) ################################################################################ + endif endif diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index c2e022c4ae9cda3232fef8e2c415a1a580ba6c02..7ae48fec8e3a59ac0e0d3198b9ea293df6ab7afa 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -211,6 +211,7 @@ SUNWprivate_1.1 { Java_java_lang_SecurityManager_getClassContext; Java_java_lang_Shutdown_halt0; Java_java_lang_String_intern; + Java_java_lang_StringUTF16_isBigEndian; Java_java_lang_System_identityHashCode; Java_java_lang_System_initProperties; Java_java_lang_System_mapLibraryName; diff --git a/jdk/make/mapfiles/libjava/reorder-sparc b/jdk/make/mapfiles/libjava/reorder-sparc index 5ae7ccabd3fcc98b13896c5e6515d3f507ed67ff..3994c916c2d5cd75b1fb17ab2cbd790a10041cec 100644 --- a/jdk/make/mapfiles/libjava/reorder-sparc +++ b/jdk/make/mapfiles/libjava/reorder-sparc @@ -57,6 +57,7 @@ text: .text%Java_java_io_UnixFileSystem_list; text: .text%JNU_ClassString; text: .text%JNU_CopyObjectArray; text: .text%Java_java_lang_String_intern; +text: .text%Java_java_lang_StringUTF16_isBigEndian; text: .text%Java_java_lang_ClassLoader_findLoadedClass0; text: .text%Java_java_lang_ClassLoader_findBootstrapClass; text: .text%Java_java_lang_Throwable_fillInStackTrace; diff --git a/jdk/make/mapfiles/libjava/reorder-sparcv9 b/jdk/make/mapfiles/libjava/reorder-sparcv9 index f10986626b0d6cb85e1de12328cf0107945cf7c1..63a667f01240cb9e5cd20809e5bc97a9d54f5ae1 100644 --- a/jdk/make/mapfiles/libjava/reorder-sparcv9 +++ b/jdk/make/mapfiles/libjava/reorder-sparcv9 @@ -29,6 +29,7 @@ text: .text%Java_sun_reflect_Reflection_getCallerClass__; text: .text%Java_sun_reflect_Reflection_getCallerClass__I; text: .text%Java_java_lang_Class_forName0; text: .text%Java_java_lang_String_intern; +text: .text%Java_java_lang_StringUTF16_isBigEndian; text: .text%Java_java_lang_Float_floatToRawIntBits; text: .text%Java_java_lang_Double_doubleToRawLongBits; text: .text%Java_java_lang_ClassLoader_findLoadedClass0; diff --git a/jdk/make/mapfiles/libjava/reorder-x86 b/jdk/make/mapfiles/libjava/reorder-x86 index 03609c1891685542fabde83e7187e75626279d23..c6c3fced9f6a7f26185bcd3b3de13e7526ea2888 100644 --- a/jdk/make/mapfiles/libjava/reorder-x86 +++ b/jdk/make/mapfiles/libjava/reorder-x86 @@ -31,6 +31,7 @@ text: .text%Java_sun_reflect_Reflection_getCallerClass__; text: .text%Java_sun_reflect_Reflection_getCallerClass__I; text: .text%Java_java_lang_Class_forName0; text: .text%Java_java_lang_String_intern; +text: .text%Java_java_lang_StringUTF16_isBigEndian; text: .text%Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0; text: .text%Java_java_lang_Throwable_fillInStackTrace; text: .text%Java_java_lang_System_setOut0; diff --git a/jdk/make/mapfiles/libnio/mapfile-macosx b/jdk/make/mapfiles/libnio/mapfile-macosx index 7ce9c50fde59e44ef255d758fcdf433253115017..97207e2c816f0bbd78e2862eeed279caf6c7d178 100644 --- a/jdk/make/mapfiles/libnio/mapfile-macosx +++ b/jdk/make/mapfiles/libnio/mapfile-macosx @@ -75,6 +75,7 @@ SUNWprivate_1.1 { Java_sun_nio_ch_IOUtil_makePipe; Java_sun_nio_ch_IOUtil_randomBytes; Java_sun_nio_ch_IOUtil_setfdVal; + Java_sun_nio_ch_IOUtil_iovMax; Java_sun_nio_ch_KQueue_kqueue; Java_sun_nio_ch_KQueue_keventRegister; Java_sun_nio_ch_KQueue_keventPoll; diff --git a/jdk/make/src/classes/build/tools/charsetmapping/DBCS.java b/jdk/make/src/classes/build/tools/charsetmapping/DBCS.java index bd4bd7140f6b1c0407e24289438f8a8c4198bb36..9ebadde8c435417148221fa441a270d27aee3eeb 100644 --- a/jdk/make/src/classes/build/tools/charsetmapping/DBCS.java +++ b/jdk/make/src/classes/build/tools/charsetmapping/DBCS.java @@ -197,6 +197,7 @@ public class DBCS { .replace("$B1MAX$" , "0x" + Integer.toString(b1Max, 16)) .replace("$B2MIN$" , "0x" + Integer.toString(b2Min, 16)) .replace("$B2MAX$" , "0x" + Integer.toString(b2Max, 16)) + .replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false") .replace("$B2C$", b2c) .replace("$C2BLENGTH$", "0x" + Integer.toString(c2bOff, 16)) .replace("$NONROUNDTRIP_B2C$", b2cNR) diff --git a/jdk/make/src/classes/build/tools/charsetmapping/SBCS.java b/jdk/make/src/classes/build/tools/charsetmapping/SBCS.java index fa294f13b9bf9c5d1e6a2132192ede90fcfccac6..02c8d63fb6a970ebb55e7d74173c967fa9fba46f 100644 --- a/jdk/make/src/classes/build/tools/charsetmapping/SBCS.java +++ b/jdk/make/src/classes/build/tools/charsetmapping/SBCS.java @@ -175,6 +175,9 @@ public class SBCS { else line = " return (cs instanceof " + clzName + ");"; } + if (line.indexOf("$ASCIICOMPATIBLE$") != -1) { + line = line.replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false"); + } if (line.indexOf("$B2CTABLE$") != -1) { line = line.replace("$B2CTABLE$", b2c); } diff --git a/jdk/make/src/classes/build/tools/x11wrappergen/WrapperGenerator.java b/jdk/make/src/classes/build/tools/x11wrappergen/WrapperGenerator.java index e3a68c42afb1901d8a351e5275bc8c25df6be1b3..60888904b890385d837b41fd19d0087d12bf435d 100644 --- a/jdk/make/src/classes/build/tools/x11wrappergen/WrapperGenerator.java +++ b/jdk/make/src/classes/build/tools/x11wrappergen/WrapperGenerator.java @@ -841,7 +841,7 @@ public class WrapperGenerator { pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" ); pw.println("package "+package_name+";\n"); - pw.println("import sun.misc.*;\n"); + pw.println("import jdk.internal.misc.Unsafe;\n"); pw.println("import sun.util.logging.PlatformLogger;"); String baseClass = stp.getBaseClass(); if (baseClass == null) { @@ -941,7 +941,7 @@ public class WrapperGenerator { pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" ); pw.println("package "+package_name+";\n"); - pw.println("import sun.misc.Unsafe;\n"); + pw.println("import jdk.internal.misc.Unsafe;\n"); pw.println("class " + ft.getName() + " {"); pw.println("\tprivate static Unsafe unsafe = XlibWrapper.unsafe;"); pw.println("\tprivate boolean __executed = false;"); diff --git a/jdk/src/demo/share/jvmti/agent_util/agent_util.h b/jdk/src/demo/share/jvmti/agent_util/agent_util.h index 44882d7121655505dc15d747c445dbaff12755fb..2237097ab30654cd71f82d7a86c85a882415733d 100644 --- a/jdk/src/demo/share/jvmti/agent_util/agent_util.h +++ b/jdk/src/demo/share/jvmti/agent_util/agent_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -65,6 +65,51 @@ void deallocate(jvmtiEnv *jvmti, void *ptr); void *allocate(jvmtiEnv *jvmti, jint len); void add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name); +#ifdef STATIC_BUILD +/* Macros for handling declaration of static/dynamic + * Agent library Load/Attach/Unload functions + * + * DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload + * generate the appropriate entrypoint names based on static + * versus dynamic builds. + * + * STATIC_BUILD must be defined to build static versions of these libraries. + * LIBRARY_NAME must be set to the name of the library for static builds. + */ +#define ADD_LIB_NAME3(name, lib) name ## lib +#define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib) +#define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME) + +#define DEF_Agent_OnLoad \ +ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \ +{ \ + jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \ + return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \ +} \ +jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_) + +#define DEF_Agent_OnAttach \ +ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \ +{ \ + jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \ + return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \ +} \ +jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_) + +#define DEF_Agent_OnUnload \ +ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \ +{ \ + void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \ + ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \ +} \ +void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_) + +#else +#define DEF_Agent_OnLoad Agent_OnLoad +#define DEF_Agent_OnAttach Agent_OnAttach +#define DEF_Agent_OnUnload Agent_OnUnload +#endif + #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ diff --git a/jdk/src/demo/share/jvmti/compiledMethodLoad/compiledMethodLoad.c b/jdk/src/demo/share/jvmti/compiledMethodLoad/compiledMethodLoad.c index 72c9717a5cb48cfdfdcc46c239bfc475a19c9218..92d123ea3ce738deee31e97a917bf3526e4a8d1b 100644 --- a/jdk/src/demo/share/jvmti/compiledMethodLoad/compiledMethodLoad.c +++ b/jdk/src/demo/share/jvmti/compiledMethodLoad/compiledMethodLoad.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -225,7 +225,7 @@ compiled_method_load(jvmtiEnv *jvmti, jmethodID method, jint code_size, * event here. */ JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *vm, char *options, void *reserved) +DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jint rc; jvmtiError err; @@ -272,6 +272,6 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) /* Agent_OnUnload() is called last */ JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *vm) +DEF_Agent_OnUnload(JavaVM *vm) { } diff --git a/jdk/src/demo/share/jvmti/gctest/gctest.c b/jdk/src/demo/share/jvmti/gctest/gctest.c index 96fc83d0cb74ecd9fd2ea7083861d398ed10b967..848e7e07c1a3569c77ee0cf42b7537a94a979287 100644 --- a/jdk/src/demo/share/jvmti/gctest/gctest.c +++ b/jdk/src/demo/share/jvmti/gctest/gctest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -148,7 +148,7 @@ gc_finish(jvmtiEnv* jvmti_env) /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *vm, char *options, void *reserved) +DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jint rc; jvmtiError err; @@ -193,6 +193,6 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) /* Agent_OnUnload() is called last */ JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *vm) +DEF_Agent_OnUnload(JavaVM *vm) { } diff --git a/jdk/src/demo/share/jvmti/heapTracker/heapTracker.c b/jdk/src/demo/share/jvmti/heapTracker/heapTracker.c index ebbcf73de5a3d05011dff45460ec57c35725ff2f..3af21846245b65877d0388885f7c35dc4f3a06b1 100644 --- a/jdk/src/demo/share/jvmti/heapTracker/heapTracker.c +++ b/jdk/src/demo/share/jvmti/heapTracker/heapTracker.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -894,7 +894,7 @@ parse_agent_options(char *options) * loaded. This is the first code executed. */ JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *vm, char *options, void *reserved) +DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { static GlobalAgentData data; jvmtiEnv *jvmti; @@ -1010,7 +1010,7 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) * unloaded. This is the last code executed. */ JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *vm) +DEF_Agent_OnUnload(JavaVM *vm) { /* Skip any cleanup, VM is about to die anyway */ } diff --git a/jdk/src/demo/share/jvmti/heapTracker/heapTracker.h b/jdk/src/demo/share/jvmti/heapTracker/heapTracker.h index dcfc4fd8514d613c905baf8eba9f7b1073fd5beb..8d63f156b7159330bba75b2976db6861cf4d231d 100644 --- a/jdk/src/demo/share/jvmti/heapTracker/heapTracker.h +++ b/jdk/src/demo/share/jvmti/heapTracker/heapTracker.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -64,9 +64,4 @@ #include "agent_util.h" -/* Agent library externals to export. */ - -JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved); -JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm); - #endif diff --git a/jdk/src/demo/share/jvmti/heapViewer/heapViewer.c b/jdk/src/demo/share/jvmti/heapViewer/heapViewer.c index f6a6e5eb4887dc4748d0d4dfd3c3d6cf32eb8858..35ed907b84ae92d83092850c4116c99b626d3f1b 100644 --- a/jdk/src/demo/share/jvmti/heapViewer/heapViewer.c +++ b/jdk/src/demo/share/jvmti/heapViewer/heapViewer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -235,7 +235,7 @@ vmDeath(jvmtiEnv *jvmti, JNIEnv *env) /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *vm, char *options, void *reserved) +DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jint rc; jvmtiError err; @@ -283,6 +283,6 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) /* Agent_OnUnload() is called last */ JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *vm) +DEF_Agent_OnUnload(JavaVM *vm) { } diff --git a/jdk/src/demo/share/jvmti/minst/minst.c b/jdk/src/demo/share/jvmti/minst/minst.c index 45da43ea45879a4339bdac47bc4cc358016aa19a..8317c1d3d61afb2a6a64ccc17586b5d6bf3a1b2a 100644 --- a/jdk/src/demo/share/jvmti/minst/minst.c +++ b/jdk/src/demo/share/jvmti/minst/minst.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -373,7 +373,7 @@ parse_agent_options(char *options) * loaded. This is the first code executed. */ JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *vm, char *options, void *reserved) +DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { static GlobalAgentData data; jvmtiEnv *jvmti; @@ -467,7 +467,7 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) * unloaded. This is the last code executed. */ JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *vm) +DEF_Agent_OnUnload(JavaVM *vm) { /* Make sure all malloc/calloc/strdup space is freed */ if ( gdata->include != NULL ) { diff --git a/jdk/src/demo/share/jvmti/minst/minst.h b/jdk/src/demo/share/jvmti/minst/minst.h index b7cf45a89bf97f1361e515aff335f999c1f941cf..d852ad4dcb8af3803ed647eccd1349587507c17e 100644 --- a/jdk/src/demo/share/jvmti/minst/minst.h +++ b/jdk/src/demo/share/jvmti/minst/minst.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -64,9 +64,4 @@ #include "agent_util.h" -/* Agent library externals to export. */ - -JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved); -JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm); - #endif diff --git a/jdk/src/demo/share/jvmti/mtrace/mtrace.c b/jdk/src/demo/share/jvmti/mtrace/mtrace.c index 05686a7ec70e33689536bc6fd053b644e3c5ef6d..82b9e662e407b21dbc18633f1df250d8ae471b20 100644 --- a/jdk/src/demo/share/jvmti/mtrace/mtrace.c +++ b/jdk/src/demo/share/jvmti/mtrace/mtrace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -697,7 +697,7 @@ parse_agent_options(char *options) * loaded. This is the first code executed. */ JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *vm, char *options, void *reserved) +DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { static GlobalAgentData data; jvmtiEnv *jvmti; @@ -795,7 +795,7 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) * unloaded. This is the last code executed. */ JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *vm) +DEF_Agent_OnUnload(JavaVM *vm) { /* Make sure all malloc/calloc/strdup space is freed */ if ( gdata->include != NULL ) { diff --git a/jdk/src/demo/share/jvmti/mtrace/mtrace.h b/jdk/src/demo/share/jvmti/mtrace/mtrace.h index c3130b88952d107c517dc0705eb13557c8cd23a2..39f483ddf140f9ea3255ba841382f78a17d1349e 100644 --- a/jdk/src/demo/share/jvmti/mtrace/mtrace.h +++ b/jdk/src/demo/share/jvmti/mtrace/mtrace.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -64,9 +64,4 @@ #include "agent_util.h" -/* Agent library externals to export. */ - -JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved); -JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm); - #endif diff --git a/jdk/src/demo/share/jvmti/versionCheck/versionCheck.c b/jdk/src/demo/share/jvmti/versionCheck/versionCheck.c index 441e488a821594b6333075a7fc77ce1fcf47485a..0ed58263b261bd6fae1232fc6222b1b787eee174 100644 --- a/jdk/src/demo/share/jvmti/versionCheck/versionCheck.c +++ b/jdk/src/demo/share/jvmti/versionCheck/versionCheck.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -89,7 +89,7 @@ vm_init(jvmtiEnv *jvmti, JNIEnv *env, jthread thread) /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *vm, char *options, void *reserved) +DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jint rc; jvmtiError err; @@ -116,6 +116,6 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) /* Agent_OnUnload() is called last */ JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *vm) +DEF_Agent_OnUnload(JavaVM *vm) { } diff --git a/jdk/src/demo/share/jvmti/waiters/Monitor.hpp b/jdk/src/demo/share/jvmti/waiters/Monitor.hpp index f067e8c65c85795184bd5e1b6ff0059b81240070..2906e5779f6d271e2f8fa63845d94f39fe63b995 100644 --- a/jdk/src/demo/share/jvmti/waiters/Monitor.hpp +++ b/jdk/src/demo/share/jvmti/waiters/Monitor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,10 @@ * this sample code. */ +#ifdef STATIC_BUILD +#define Monitor WaiterMonitor +#endif + /* C++ Monitor class */ diff --git a/jdk/src/demo/share/jvmti/waiters/Thread.cpp b/jdk/src/demo/share/jvmti/waiters/Thread.cpp index 065a40dd51686e0aa4beb4d07f14632240063333..589976963e04eadb7d6a03dfa1cc0a7cf2b0716d 100644 --- a/jdk/src/demo/share/jvmti/waiters/Thread.cpp +++ b/jdk/src/demo/share/jvmti/waiters/Thread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,9 @@ * this sample code. */ +#ifdef STATIC_BUILD +#define Thread WaiterThread +#endif #include <stdio.h> #include <stdlib.h> diff --git a/jdk/src/demo/share/jvmti/waiters/waiters.cpp b/jdk/src/demo/share/jvmti/waiters/waiters.cpp index 34b79f383081779ebafdf18d6c9a820afe801095..cf38e00e1601f00c9b2617bc8ab24176deb2b3a9 100644 --- a/jdk/src/demo/share/jvmti/waiters/waiters.cpp +++ b/jdk/src/demo/share/jvmti/waiters/waiters.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -243,7 +243,7 @@ extern "C" { /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ JNIEXPORT jint JNICALL - Agent_OnLoad(JavaVM *vm, char *options, void *reserved) + DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jvmtiEnv *jvmti; jint rc; @@ -288,7 +288,7 @@ extern "C" { /* Agent_OnUnload() is called last */ JNIEXPORT void JNICALL - Agent_OnUnload(JavaVM *vm) + DEF_Agent_OnUnload(JavaVM *vm) { } diff --git a/jdk/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java b/jdk/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java index a7a954597e5a192d718e9358841145b981939093..9cb294f67f0b7abdc92884e44b41570fe8d846de 100644 --- a/jdk/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java +++ b/jdk/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java @@ -34,7 +34,7 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * AsynchronousChannelGroup implementation based on the AIX pollset framework. diff --git a/jdk/src/java.base/linux/classes/sun/nio/ch/EPoll.java b/jdk/src/java.base/linux/classes/sun/nio/ch/EPoll.java index bb2b9e5171fb9416eb98b1d9ef9ec0773f789345..72fe9950621987979906483c3135b35db000d4f5 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/ch/EPoll.java +++ b/jdk/src/java.base/linux/classes/sun/nio/ch/EPoll.java @@ -26,7 +26,7 @@ package sun.nio.ch; import java.io.IOException; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Provides access to the Linux epoll facility. diff --git a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java index 11a40a0e86284bb836d9d76eee12d52e92eb25b4..dba638e8da9fef67a5afd9706af145739325aaa3 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java @@ -29,7 +29,7 @@ import java.nio.file.attribute.*; import java.util.Map; import java.util.Set; import java.io.IOException; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static sun.nio.fs.UnixNativeDispatcher.*; import static sun.nio.fs.UnixConstants.*; diff --git a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java index d3960b277011a5f785ecd8ebe9cd987135e65186..18b880c550f1257ecfc61c291ae993df5138143d 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java @@ -29,7 +29,7 @@ import java.nio.file.*; import java.nio.ByteBuffer; import java.io.IOException; import java.util.*; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.LinuxNativeDispatcher.*; diff --git a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java index 19079d72878ca1f1c82853fab0e189cb23eb818d..02af6a539d6b88d6f7201e7e1fd63d482143479a 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java @@ -30,7 +30,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import java.io.IOException; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static sun.nio.fs.UnixNativeDispatcher.*; import static sun.nio.fs.UnixConstants.*; diff --git a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueue.java b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueue.java index b98dacdfc533f98bf5afaa1db9d008f28e90c66b..f2be5339a76317a7af2075eeb6278b74548db017 100644 --- a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueue.java +++ b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueue.java @@ -26,7 +26,7 @@ package sun.nio.ch; import java.io.IOException; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Provides access to the BSD kqueue facility. diff --git a/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c index 7482d6ccc4c0ba439c4d4e30487848c49a6a289f..82f63169edd6198bbe385d15369b6bcb03e6fbda 100644 --- a/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c +++ b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c @@ -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 @@ -35,13 +35,15 @@ #include "java_props_macosx.h" - // need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded static void *getJRSFramework() { static void *jrsFwk = NULL; +#ifndef STATIC_BUILD +// JavaRuntimeSupport doesn't support static Java runtimes if (jrsFwk == NULL) { jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL); } +#endif return jrsFwk; } diff --git a/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c b/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c index 2f3409dc0da412d52fe6e6db1989543913f6750f..46a4a06beae5399c8742482ed2222b1396c03594 100644 --- a/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c +++ b/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c @@ -245,6 +245,8 @@ static InvocationFunctions *GetExportedJNIFunctions() { return sExportedJNIFunctions = fxns; } +#ifndef STATIC_BUILD + JNIEXPORT jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args) { InvocationFunctions *ifn = GetExportedJNIFunctions(); @@ -265,6 +267,7 @@ JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs) { if (ifn == NULL) return JNI_ERR; return ifn->GetCreatedJavaVMs(vmBuf, bufLen, nVMs); } +#endif /* * Allow JLI-aware launchers to specify a client/server preference @@ -303,7 +306,12 @@ static void *apple_main (void *arg) objc_registerThreadWithCollector(); if (main_fptr == NULL) { +#ifdef STATIC_BUILD + extern int main(int argc, char **argv); + main_fptr = &main; +#else main_fptr = (int (*)())dlsym(RTLD_DEFAULT, "main"); +#endif if (main_fptr == NULL) { JLI_ReportErrorMessageSys("error locating main entrypoint\n"); exit(1); @@ -588,6 +596,9 @@ GetJVMPath(const char *jrepath, const char *jvmtype, JLI_TraceLauncher("Does `%s' exist ... ", jvmpath); +#ifdef STATIC_BUILD + return JNI_TRUE; +#else if (stat(jvmpath, &s) == 0) { JLI_TraceLauncher("yes.\n"); return JNI_TRUE; @@ -595,6 +606,7 @@ GetJVMPath(const char *jrepath, const char *jvmtype, JLI_TraceLauncher("no.\n"); return JNI_FALSE; } +#endif } /* @@ -607,10 +619,18 @@ GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative) if (GetApplicationHome(path, pathsize)) { /* Is JRE co-located with the application? */ +#ifdef STATIC_BUILD + char jvm_cfg[MAXPATHLEN]; + JLI_Snprintf(jvm_cfg, sizeof(jvm_cfg), "%s/lib/jvm.cfg", path); + if (access(jvm_cfg, F_OK) == 0) { + return JNI_TRUE; + } +#else JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path); if (access(libjava, F_OK) == 0) { return JNI_TRUE; } +#endif /* ensure storage for path + /jre + NULL */ if ((JLI_StrLen(path) + 4 + 1) > (size_t) pathsize) { JLI_TraceLauncher("Insufficient space to store JRE path\n"); @@ -629,6 +649,24 @@ GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative) Dl_info selfInfo; dladdr(&GetJREPath, &selfInfo); +#ifdef STATIC_BUILD + char jvm_cfg[MAXPATHLEN]; + char *p = NULL; + strncpy(jvm_cfg, selfInfo.dli_fname, MAXPATHLEN); + p = strrchr(jvm_cfg, '/'); *p = '\0'; + p = strrchr(jvm_cfg, '/'); + if (strcmp(p, "/.") == 0) { + *p = '\0'; + p = strrchr(jvm_cfg, '/'); *p = '\0'; + } + else *p = '\0'; + strncpy(path, jvm_cfg, pathsize); + strncat(jvm_cfg, "/lib/jvm.cfg", MAXPATHLEN); + if (access(jvm_cfg, F_OK) == 0) { + return JNI_TRUE; + } +#endif + char *realPathToSelf = realpath(selfInfo.dli_fname, path); if (realPathToSelf != path) { return JNI_FALSE; @@ -664,7 +702,11 @@ LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) JLI_TraceLauncher("JVM path is %s\n", jvmpath); +#ifndef STATIC_BUILD libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL); +#else + libjvm = dlopen(NULL, RTLD_FIRST); +#endif if (libjvm == NULL) { JLI_ReportErrorMessage(DLL_ERROR1, __LINE__); JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); @@ -714,9 +756,14 @@ SetExecname(char **argv) char* exec_path = NULL; { Dl_info dlinfo; - int (*fptr)(); +#ifdef STATIC_BUILD + void *fptr; + fptr = (void *)&SetExecname; +#else + int (*fptr)(); fptr = (int (*)())dlsym(RTLD_DEFAULT, "main"); +#endif if (fptr == NULL) { JLI_ReportErrorMessage(DLL_ERROR3, dlerror()); return JNI_FALSE; diff --git a/jdk/src/java.base/share/classes/java/io/File.java b/jdk/src/java.base/share/classes/java/io/File.java index 63e6d571ed282a14b44035065d31a026edfd8e1e..6137d0acd29abbeda3b3f477b6d580e4afe390dd 100644 --- a/jdk/src/java.base/share/classes/java/io/File.java +++ b/jdk/src/java.base/share/classes/java/io/File.java @@ -2184,10 +2184,10 @@ public class File private static final long PATH_OFFSET; private static final long PREFIX_LENGTH_OFFSET; - private static final sun.misc.Unsafe UNSAFE; + private static final jdk.internal.misc.Unsafe UNSAFE; static { try { - sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); PATH_OFFSET = unsafe.objectFieldOffset( File.class.getDeclaredField("path")); PREFIX_LENGTH_OFFSET = unsafe.objectFieldOffset( diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java index f2bf5f017952edd976cdba3e9d0e52e215f3b2a9..779257e87c0a4607b132e9d9b34a34def51e532d 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -40,7 +40,7 @@ import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static java.io.ObjectStreamClass.processQueue; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.reflect.misc.ReflectUtil; /** 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 aa516a15d67bfa713347da90d565f2b065549826..762706c1e88bb2d60763f9781ea0bc15d30e2643 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -48,7 +48,7 @@ import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.reflect.CallerSensitive; import sun.reflect.Reflection; import sun.reflect.ReflectionFactory; 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 a92160007314c00ed5fb92f02f0a0235e3d44d2a..65f3c497b18576dd665ce1926b5c214694a86aea 100644 --- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -31,6 +31,12 @@ import java.util.Spliterator; import java.util.stream.IntStream; import java.util.stream.StreamSupport; +import static java.lang.String.COMPACT_STRINGS; +import static java.lang.String.UTF16; +import static java.lang.String.LATIN1; +import static java.lang.String.checkIndex; +import static java.lang.String.checkOffset; + /** * A mutable sequence of characters. * <p> @@ -51,7 +57,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { /** * The value is used for character storage. */ - char[] value; + byte[] value; + + /** + * The id of the encoding used to encode the bytes in {@code value}. + */ + byte coder; /** * The count is the number of characters used. @@ -68,7 +79,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * Creates an AbstractStringBuilder of the specified capacity. */ AbstractStringBuilder(int capacity) { - value = new char[capacity]; + if (COMPACT_STRINGS) { + value = new byte[capacity]; + coder = LATIN1; + } else { + value = StringUTF16.newBytesFor(capacity); + coder = UTF16; + } } /** @@ -90,7 +107,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @return the current capacity */ public int capacity() { - return value.length; + return value.length >> coder; } /** @@ -110,8 +127,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @param minimumCapacity the minimum desired capacity. */ public void ensureCapacity(int minimumCapacity) { - if (minimumCapacity > 0) + if (minimumCapacity > 0) { ensureCapacityInternal(minimumCapacity); + } } /** @@ -120,24 +138,48 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { */ private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code - if (minimumCapacity - value.length > 0) + int capacity = value.length >> coder; + if (minimumCapacity - capacity > 0) { expandCapacity(minimumCapacity); + } } /** * This implements the expansion semantics of ensureCapacity with no * size check or synchronization. */ - void expandCapacity(int minimumCapacity) { - int newCapacity = value.length * 2 + 2; - if (newCapacity - minimumCapacity < 0) + private void expandCapacity(int minimumCapacity) { + int newCapacity = (value.length >> coder) * 2 + 2; + if (newCapacity - minimumCapacity < 0) { newCapacity = minimumCapacity; + } if (newCapacity < 0) { - if (minimumCapacity < 0) // overflow + if (minimumCapacity < 0) {// overflow throw new OutOfMemoryError(); + } newCapacity = Integer.MAX_VALUE; } - value = Arrays.copyOf(value, newCapacity); + if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) { + if (minimumCapacity >= StringUTF16.MAX_LENGTH) { + throw new OutOfMemoryError(); + } + newCapacity = StringUTF16.MAX_LENGTH; + } + this.value = Arrays.copyOf(value, newCapacity << coder); + } + + /** + * If the coder is "isLatin1", this inflates the internal 8-bit storage + * to 16-bit <hi=0, low> pair storage. + */ + private void inflate() { + if (!isLatin1()) { + return; + } + byte[] buf = StringUTF16.newBytesFor(value.length); + StringLatin1.inflateSB(value, buf, 0, count); + this.value = buf; + this.coder = UTF16; } /** @@ -148,8 +190,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * returned by a subsequent call to the {@link #capacity()} method. */ public void trimToSize() { - if (count < value.length) { - value = Arrays.copyOf(value, count); + int length = count << coder; + if (length < value.length) { + value = Arrays.copyOf(value, length); } } @@ -179,14 +222,17 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * {@code newLength} argument is negative. */ public void setLength(int newLength) { - if (newLength < 0) + if (newLength < 0) { throw new StringIndexOutOfBoundsException(newLength); + } ensureCapacityInternal(newLength); - if (count < newLength) { - Arrays.fill(value, count, newLength, '\0'); + if (isLatin1()) { + StringLatin1.fillNull(value, count, newLength); + } else { + StringUTF16.fillNull(value, count, newLength); + } } - count = newLength; } @@ -209,9 +255,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { */ @Override public char charAt(int index) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); - return value[index]; + checkIndex(index, count); + if (isLatin1()) { + return (char)(value[index] & 0xff); + } + return StringUTF16.charAt(value, index); } /** @@ -236,10 +284,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * sequence. */ public int codePointAt(int index) { - if ((index < 0) || (index >= count)) { - throw new StringIndexOutOfBoundsException(index); + checkIndex(index, count); + if (isLatin1()) { + return value[index] & 0xff; } - return Character.codePointAtImpl(value, index, count); + return StringUTF16.codePointAtSB(value, index, count); } /** @@ -265,10 +314,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { */ public int codePointBefore(int index) { int i = index - 1; - if ((i < 0) || (i >= count)) { + if (i < 0 || i >= count) { throw new StringIndexOutOfBoundsException(index); } - return Character.codePointBeforeImpl(value, index, 0); + if (isLatin1()) { + return value[i] & 0xff; + } + return StringUTF16.codePointBeforeSB(value, index); } /** @@ -295,7 +347,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { throw new IndexOutOfBoundsException(); } - return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex); + if (isLatin1()) { + return endIndex - beginIndex; + } + return StringUTF16.codePointCountSB(value, beginIndex, endIndex); } /** @@ -321,8 +376,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { if (index < 0 || index > count) { throw new IndexOutOfBoundsException(); } - return Character.offsetByCodePointsImpl(value, 0, count, - index, codePointOffset); + return Character.offsetByCodePoints(this, + index, codePointOffset); } /** @@ -355,13 +410,14 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { */ public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { - if (srcBegin < 0) - throw new StringIndexOutOfBoundsException(srcBegin); - if ((srcEnd < 0) || (srcEnd > count)) - throw new StringIndexOutOfBoundsException(srcEnd); - if (srcBegin > srcEnd) - throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); - System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); + checkRangeSIOOBE(srcBegin, srcEnd, count); // compatible to old version + int n = srcEnd - srcBegin; + checkRange(dstBegin, dstBegin + n, dst.length); + if (isLatin1()) { + StringLatin1.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin); + } else { + StringUTF16.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin); + } } /** @@ -379,9 +435,15 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * negative or greater than or equal to {@code length()}. */ public void setCharAt(int index, char ch) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); - value[index] = ch; + checkIndex(index, count); + if (isLatin1() && StringLatin1.canEncode(ch)) { + value[index] = (byte)ch; + } else { + if (isLatin1()) { + inflate(); + } + StringUTF16.putCharSB(value, index, ch); + } } /** @@ -418,35 +480,34 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @return a reference to this object. */ public AbstractStringBuilder append(String str) { - if (str == null) + if (str == null) { return appendNull(); + } int len = str.length(); ensureCapacityInternal(count + len); - str.getChars(0, len, value, count); + putStringAt(count, str); count += len; return this; } // Documentation in subclasses because of synchro difference public AbstractStringBuilder append(StringBuffer sb) { - if (sb == null) - return appendNull(); - int len = sb.length(); - ensureCapacityInternal(count + len); - sb.getChars(0, len, value, count); - count += len; - return this; + return this.append((AbstractStringBuilder)sb); } /** * @since 1.8 */ AbstractStringBuilder append(AbstractStringBuilder asb) { - if (asb == null) + if (asb == null) { return appendNull(); + } int len = asb.length(); ensureCapacityInternal(count + len); - asb.getChars(0, len, value, count); + if (getCoder() != asb.getCoder()) { + inflate(); + } + asb.getBytes(value, count, coder); count += len; return this; } @@ -454,25 +515,35 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { // Documentation in subclasses because of synchro difference @Override public AbstractStringBuilder append(CharSequence s) { - if (s == null) + if (s == null) { return appendNull(); - if (s instanceof String) + } + if (s instanceof String) { return this.append((String)s); - if (s instanceof AbstractStringBuilder) + } + if (s instanceof AbstractStringBuilder) { return this.append((AbstractStringBuilder)s); - + } return this.append(s, 0, s.length()); } private AbstractStringBuilder appendNull() { - int c = count; - ensureCapacityInternal(c + 4); - final char[] value = this.value; - value[c++] = 'n'; - value[c++] = 'u'; - value[c++] = 'l'; - value[c++] = 'l'; - count = c; + ensureCapacityInternal(count + 4); + int count = this.count; + byte[] val = this.value; + if (isLatin1()) { + val[count++] = 'n'; + val[count++] = 'u'; + val[count++] = 'l'; + val[count++] = 'l'; + } else { + checkOffset(count + 4, val.length >> 1); + StringUTF16.putChar(val, count++, 'n'); + StringUTF16.putChar(val, count++, 'u'); + StringUTF16.putChar(val, count++, 'l'); + StringUTF16.putChar(val, count++, 'l'); + } + this.count = count; return this; } @@ -507,21 +578,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { */ @Override public AbstractStringBuilder append(CharSequence s, int start, int end) { - if (s == null) + if (s == null) { s = "null"; - if ((start < 0) || (start > end) || (end > s.length())) - throw new IndexOutOfBoundsException( - "start " + start + ", end " + end + ", s.length() " - + s.length()); + } + checkRange(start, end, s.length()); int len = end - start; ensureCapacityInternal(count + len); - if (s instanceof String) { - ((String)s).getChars(start, end, value, count); - } else { - for (int i = start, j = count; i < end; i++, j++) - value[j] = s.charAt(i); - } - count += len; + appendChars(s, start, end); return this; } @@ -544,8 +607,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { public AbstractStringBuilder append(char[] str) { int len = str.length; ensureCapacityInternal(count + len); - System.arraycopy(str, 0, value, count, len); - count += len; + appendChars(str, 0, len); return this; } @@ -572,10 +634,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * or {@code offset+len > str.length} */ public AbstractStringBuilder append(char str[], int offset, int len) { - if (len > 0) // let arraycopy report AIOOBE for len < 0 - ensureCapacityInternal(count + len); - System.arraycopy(str, offset, value, count, len); - count += len; + int end = offset + len; + checkRange(offset, end, str.length); + ensureCapacityInternal(count + len); + appendChars(str, offset, end); return this; } @@ -592,20 +654,39 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @return a reference to this object. */ public AbstractStringBuilder append(boolean b) { - if (b) { - ensureCapacityInternal(count + 4); - value[count++] = 't'; - value[count++] = 'r'; - value[count++] = 'u'; - value[count++] = 'e'; + ensureCapacityInternal(count + (b ? 4 : 5)); + int count = this.count; + byte[] val = this.value; + if (isLatin1()) { + if (b) { + val[count++] = 't'; + val[count++] = 'r'; + val[count++] = 'u'; + val[count++] = 'e'; + } else { + val[count++] = 'f'; + val[count++] = 'a'; + val[count++] = 'l'; + val[count++] = 's'; + val[count++] = 'e'; + } } else { - ensureCapacityInternal(count + 5); - value[count++] = 'f'; - value[count++] = 'a'; - value[count++] = 'l'; - value[count++] = 's'; - value[count++] = 'e'; + if (b) { + checkOffset(count + 4, val.length >> 1); + StringUTF16.putChar(val, count++, 't'); + StringUTF16.putChar(val, count++, 'r'); + StringUTF16.putChar(val, count++, 'u'); + StringUTF16.putChar(val, count++, 'e'); + } else { + checkOffset(count + 5, val.length >> 1); + StringUTF16.putChar(val, count++, 'f'); + StringUTF16.putChar(val, count++, 'a'); + StringUTF16.putChar(val, count++, 'l'); + StringUTF16.putChar(val, count++, 's'); + StringUTF16.putChar(val, count++, 'e'); + } } + this.count = count; return this; } @@ -627,7 +708,14 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { @Override public AbstractStringBuilder append(char c) { ensureCapacityInternal(count + 1); - value[count++] = c; + if (isLatin1() && StringLatin1.canEncode(c)) { + value[count++] = (byte)c; + } else { + if (isLatin1()) { + inflate(); + } + StringUTF16.putCharSB(value, count++, c); + } return this; } @@ -652,7 +740,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { : Integer.stringSize(i); int spaceNeeded = count + appendedLength; ensureCapacityInternal(spaceNeeded); - Integer.getChars(i, spaceNeeded, value); + if (isLatin1()) { + Integer.getChars(i, spaceNeeded, value); + } else { + byte[] val = this.value; + checkOffset(spaceNeeded, val.length >> 1); + Integer.getCharsUTF16(i, spaceNeeded, val); + } count = spaceNeeded; return this; } @@ -678,7 +772,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { : Long.stringSize(l); int spaceNeeded = count + appendedLength; ensureCapacityInternal(spaceNeeded); - Long.getChars(l, spaceNeeded, value); + if (isLatin1()) { + Long.getChars(l, spaceNeeded, value); + } else { + byte[] val = this.value; + checkOffset(spaceNeeded, val.length >> 1); + Long.getCharsUTF16(l, spaceNeeded, val); + } count = spaceNeeded; return this; } @@ -732,15 +832,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * greater than {@code end}. */ public AbstractStringBuilder delete(int start, int end) { - if (start < 0) - throw new StringIndexOutOfBoundsException(start); - if (end > count) + if (end > count) { end = count; - if (start > end) - throw new StringIndexOutOfBoundsException(); + } + checkRangeSIOOBE(start, end, count); int len = end - start; if (len > 0) { - System.arraycopy(value, start+len, value, start, count-end); + shift(end, -len); count -= len; } return this; @@ -766,20 +864,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * {@code codePoint} isn't a valid Unicode code point */ public AbstractStringBuilder appendCodePoint(int codePoint) { - final int count = this.count; - if (Character.isBmpCodePoint(codePoint)) { - ensureCapacityInternal(count + 1); - value[count] = (char) codePoint; - this.count = count + 1; - } else if (Character.isValidCodePoint(codePoint)) { - ensureCapacityInternal(count + 2); - Character.toSurrogates(codePoint, value, count); - this.count = count + 2; - } else { - throw new IllegalArgumentException(); + return append((char)codePoint); } - return this; + return append(Character.toChars(codePoint)); } /** @@ -800,9 +888,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * {@code length()}. */ public AbstractStringBuilder deleteCharAt(int index) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); - System.arraycopy(value, index+1, value, index, count-index-1); + checkIndex(index, count); + shift(index + 1, -1); count--; return this; } @@ -827,22 +914,16 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * greater than {@code end}. */ public AbstractStringBuilder replace(int start, int end, String str) { - if (start < 0) - throw new StringIndexOutOfBoundsException(start); - if (start > count) - throw new StringIndexOutOfBoundsException("start > length()"); - if (start > end) - throw new StringIndexOutOfBoundsException("start > end"); - - if (end > count) + if (end > count) { end = count; + } + checkRangeSIOOBE(start, end, count); int len = str.length(); int newCount = count + len - (end - start); ensureCapacityInternal(newCount); - - System.arraycopy(value, end, value, start + len, count - end); - str.getChars(value, start); + shift(end, newCount - count); count = newCount; + putStringAt(start, str); return this; } @@ -907,13 +988,16 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * greater than {@code end}. */ public String substring(int start, int end) { - if (start < 0) - throw new StringIndexOutOfBoundsException(start); - if (end > count) - throw new StringIndexOutOfBoundsException(end); - if (start > end) - throw new StringIndexOutOfBoundsException(end - start); - return new String(value, start, end - start); + checkRangeSIOOBE(start, end, count); + if (isLatin1()) { + return StringLatin1.newString(value, start, end - start); + } + return StringUTF16.newStringSB(value, start, end - start); + } + + private void shift(int offset, int n) { + System.arraycopy(value, offset << coder, + value, (offset + n) << coder, (count - offset) << coder); } /** @@ -940,16 +1024,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { public AbstractStringBuilder insert(int index, char[] str, int offset, int len) { - if ((index < 0) || (index > length())) - throw new StringIndexOutOfBoundsException(index); - if ((offset < 0) || (len < 0) || (offset > str.length - len)) - throw new StringIndexOutOfBoundsException( - "offset " + offset + ", len " + len + ", str.length " - + str.length); + checkOffset(index, count); + checkRangeSIOOBE(offset, offset + len, str.length); ensureCapacityInternal(count + len); - System.arraycopy(value, index, value, index + len, count - index); - System.arraycopy(str, offset, value, index, len); + shift(index, len); count += len; + putCharsAt(index, str, offset, offset + len); return this; } @@ -1008,15 +1088,15 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @throws StringIndexOutOfBoundsException if the offset is invalid. */ public AbstractStringBuilder insert(int offset, String str) { - if ((offset < 0) || (offset > length())) - throw new StringIndexOutOfBoundsException(offset); - if (str == null) + checkOffset(offset, count); + if (str == null) { str = "null"; + } int len = str.length(); ensureCapacityInternal(count + len); - System.arraycopy(value, offset, value, offset + len, count - offset); - str.getChars(value, offset); + shift(offset, len); count += len; + putStringAt(offset, str); return this; } @@ -1045,13 +1125,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @throws StringIndexOutOfBoundsException if the offset is invalid. */ public AbstractStringBuilder insert(int offset, char[] str) { - if ((offset < 0) || (offset > length())) - throw new StringIndexOutOfBoundsException(offset); + checkOffset(offset, count); int len = str.length; ensureCapacityInternal(count + len); - System.arraycopy(value, offset, value, offset + len, count - offset); - System.arraycopy(str, 0, value, offset, len); + shift(offset, len); count += len; + putCharsAt(offset, str, 0, len); return this; } @@ -1077,10 +1156,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @throws IndexOutOfBoundsException if the offset is invalid. */ public AbstractStringBuilder insert(int dstOffset, CharSequence s) { - if (s == null) + if (s == null) { s = "null"; - if (s instanceof String) + } + if (s instanceof String) { return this.insert(dstOffset, (String)s); + } return this.insert(dstOffset, s, 0, s.length()); } @@ -1128,23 +1209,19 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * {@code start} is greater than {@code end} or * {@code end} is greater than {@code s.length()} */ - public AbstractStringBuilder insert(int dstOffset, CharSequence s, - int start, int end) { - if (s == null) + public AbstractStringBuilder insert(int dstOffset, CharSequence s, + int start, int end) + { + if (s == null) { s = "null"; - if ((dstOffset < 0) || (dstOffset > this.length())) - throw new IndexOutOfBoundsException("dstOffset "+dstOffset); - if ((start < 0) || (end < 0) || (start > end) || (end > s.length())) - throw new IndexOutOfBoundsException( - "start " + start + ", end " + end + ", s.length() " - + s.length()); + } + checkOffset(dstOffset, count); + checkRange(start, end, s.length()); int len = end - start; ensureCapacityInternal(count + len); - System.arraycopy(value, dstOffset, value, dstOffset + len, - count - dstOffset); - for (int i=start; i<end; i++) - value[dstOffset++] = s.charAt(i); + shift(dstOffset, len); count += len; + putCharsAt(dstOffset, s, start, end); return this; } @@ -1191,10 +1268,18 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @throws IndexOutOfBoundsException if the offset is invalid. */ public AbstractStringBuilder insert(int offset, char c) { + checkOffset(offset, count); ensureCapacityInternal(count + 1); - System.arraycopy(value, offset, value, offset + 1, count - offset); - value[offset] = c; + shift(offset, 1); count += 1; + if (isLatin1() && StringLatin1.canEncode(c)) { + value[offset] = (byte)c; + } else { + if (isLatin1()) { + inflate(); + } + StringUTF16.putCharSB(value, offset, c); + } return this; } @@ -1326,7 +1411,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * or {@code -1} if there is no such occurrence. */ public int indexOf(String str, int fromIndex) { - return String.indexOf(value, 0, count, str, fromIndex); + return String.indexOf(value, coder, count, str, fromIndex); } /** @@ -1366,7 +1451,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * or {@code -1} if there is no such occurrence. */ public int lastIndexOf(String str, int fromIndex) { - return String.lastIndexOf(value, 0, count, str, fromIndex); + return String.lastIndexOf(value, coder, count, str, fromIndex); } /** @@ -1392,34 +1477,47 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @return a reference to this object. */ public AbstractStringBuilder reverse() { - boolean hasSurrogates = false; + byte[] val = this.value; + int count = this.count; + int coder = this.coder; int n = count - 1; - for (int j = (n-1) >> 1; j >= 0; j--) { - int k = n - j; - char cj = value[j]; - char ck = value[k]; - value[j] = ck; - value[k] = cj; - if (Character.isSurrogate(cj) || - Character.isSurrogate(ck)) { - hasSurrogates = true; + if (COMPACT_STRINGS && coder == LATIN1) { + for (int j = (n-1) >> 1; j >= 0; j--) { + int k = n - j; + byte cj = val[j]; + val[j] = val[k]; + val[k] = cj; + } + } else { + checkOffset(count, val.length >> 1); + boolean hasSurrogates = false; + for (int j = (n-1) >> 1; j >= 0; j--) { + int k = n - j; + char cj = StringUTF16.getChar(val, j); + char ck = StringUTF16.getChar(val, k); + StringUTF16.putChar(val, j, ck); + StringUTF16.putChar(val, k, cj); + if (Character.isSurrogate(cj) || + Character.isSurrogate(ck)) { + hasSurrogates = true; + } + } + if (hasSurrogates) { + reverseAllValidSurrogatePairs(val, count); } - } - if (hasSurrogates) { - reverseAllValidSurrogatePairs(); } return this; } /** Outlined helper method for reverse() */ - private void reverseAllValidSurrogatePairs() { + private void reverseAllValidSurrogatePairs(byte[] val, int count) { for (int i = 0; i < count - 1; i++) { - char c2 = value[i]; + char c2 = StringUTF16.getChar(val, i); if (Character.isLowSurrogate(c2)) { - char c1 = value[i + 1]; + char c1 = StringUTF16.getChar(val, i + 1); if (Character.isHighSurrogate(c1)) { - value[i++] = c1; - value[i] = c2; + StringUTF16.putChar(val, i++, c1); + StringUTF16.putChar(val, i, c2); } } } @@ -1444,10 +1542,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { */ @Override public IntStream chars() { + byte[] val = this.value; int count = this.count; byte coder = this.coder; + checkOffset(count, val.length >> coder); // Reuse String-based spliterator. This requires a supplier to // capture the value and count when the terminal operation is executed return StreamSupport.intStream( - () -> new String.IntCharArraySpliterator(value, 0, count, 0), + () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0) + : new StringUTF16.CharsSpliterator(val, 0, count, 0), Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED, false); } @@ -1458,10 +1559,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { */ @Override public IntStream codePoints() { + byte[] val = this.value; int count = this.count; byte coder = this.coder; + checkOffset(count, val.length >> coder); // Reuse String-based spliterator. This requires a supplier to // capture the value and count when the terminal operation is executed return StreamSupport.intStream( - () -> new String.CodePointsSpliterator(value, 0, count, 0), + () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0) + : new StringUTF16.CodePointsSpliterator(val, 0, count, 0), Spliterator.ORDERED, false); } @@ -1469,8 +1573,147 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { /** * Needed by {@code String} for the contentEquals method. */ - final char[] getValue() { + final byte[] getValue() { return value; } + /* + * Invoker guarantees it is in UTF16 (inflate itself for asb), if two + * coders are different and the dstBegin has enough space + * + * @param dstBegin the char index, not offset of byte[] + * @param coder the coder of dst[] + */ + protected void getBytes(byte dst[], int dstBegin, byte coder) { + if (this.coder == coder) { + System.arraycopy(value, 0, dst, dstBegin << coder, count << coder); + } else { // this.coder == LATIN && coder == UTF16 + StringLatin1.inflateSB(value, dst, dstBegin, count); + } + } + + /* for readObject() */ + protected void initBytes(char[] value, int off, int len) { + if (String.COMPACT_STRINGS) { + this.value = StringUTF16.compress(value, off, len); + if (this.value != null) { + this.coder = LATIN1; + return; + } + } + this.coder = UTF16; + this.value = StringUTF16.toBytes(value, off, len); + } + + final byte getCoder() { + return COMPACT_STRINGS ? coder : UTF16; + } + + final boolean isLatin1() { + return COMPACT_STRINGS && coder == LATIN1; + } + + private final void putCharsAt(int index, char[] s, int off, int end) { + if (isLatin1()) { + byte[] val = this.value; + for (int i = off, j = index; i < end; i++) { + char c = s[i]; + if (StringLatin1.canEncode(c)) { + val[j++] = (byte)c; + } else { + inflate(); + StringUTF16.putCharsSB(this.value, j, s, i, end); + return; + } + } + } else { + StringUTF16.putCharsSB(this.value, index, s, off, end); + } + } + + private final void putCharsAt(int index, CharSequence s, int off, int end) { + if (isLatin1()) { + byte[] val = this.value; + for (int i = off, j = index; i < end; i++) { + char c = s.charAt(i); + if (StringLatin1.canEncode(c)) { + val[j++] = (byte)c; + } else { + inflate(); + StringUTF16.putCharsSB(this.value, j, s, i, end); + return; + } + } + } else { + StringUTF16.putCharsSB(this.value, index, s, off, end); + } + } + + private final void putStringAt(int index, String str) { + if (getCoder() != str.coder()) { + inflate(); + } + byte[] val = this.value; + byte coder = this.coder; + checkOffset(index + str.length(), val.length >> coder); + str.getBytes(val, index, coder); + } + + private final void appendChars(char[] s, int off, int end) { + if (isLatin1()) { + byte[] val = this.value; + for (int i = off, j = count; i < end; i++) { + char c = s[i]; + if (StringLatin1.canEncode(c)) { + val[j++] = (byte)c; + } else { + count = j; + inflate(); + StringUTF16.putCharsSB(this.value, j, s, i, end); + count += end - i; + return; + } + } + } else { + StringUTF16.putCharsSB(this.value, count, s, off, end); + } + count += end - off; + } + + private final void appendChars(CharSequence s, int off, int end) { + if (isLatin1()) { + byte[] val = this.value; + for (int i = off, j = count; i < end; i++) { + char c = s.charAt(i); + if (StringLatin1.canEncode(c)) { + val[j++] = (byte)c; + } else { + count = j; + inflate(); + StringUTF16.putCharsSB(this.value, j, s, i, end); + count += end - i; + return; + } + } + } else { + StringUTF16.putCharsSB(this.value, count, s, off, end); + } + count += end - off; + } + + /* IndexOutOfBoundsException, if out of bounds */ + private static void checkRange(int start, int end, int len) { + if (start < 0 || start > end || end > len) { + throw new IndexOutOfBoundsException( + "start " + start + ", end " + end + ", length " + len); + } + } + + /* StringIndexOutOfBoundsException, if out of bounds */ + private static void checkRangeSIOOBE(int start, int end, int len) { + if (start < 0 || start > end || end > len) { + throw new StringIndexOutOfBoundsException( + "start " + start + ", end " + end + ", length " + len); + } + } } diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java index fc1e6b9f0f3e992cb315b28e893fee7907349008..77913c3187d8b927def8bd09357d9fdd21959f47 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -55,7 +55,7 @@ import java.util.Map; import java.util.HashMap; import java.util.Objects; import java.util.StringJoiner; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import jdk.internal.HotSpotIntrinsicCandidate; import sun.reflect.CallerSensitive; import sun.reflect.ConstantPool; 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 ed401dba13f9cfcff677dabbbc6eecc572551b5f..e956c3571ffbd4230948f6783015a7e1828b0792 100644 --- a/jdk/src/java.base/share/classes/java/lang/Integer.java +++ b/jdk/src/java.base/share/classes/java/lang/Integer.java @@ -29,6 +29,10 @@ import java.lang.annotation.Native; import java.util.Objects; import jdk.internal.HotSpotIntrinsicCandidate; +import static java.lang.String.COMPACT_STRINGS; +import static java.lang.String.LATIN1; +import static java.lang.String.UTF16; + /** * The {@code Integer} class wraps a value of the primitive type * {@code int} in an object. An object of type {@code Integer} @@ -138,25 +142,47 @@ public final class Integer extends Number implements Comparable<Integer> { return toString(i); } - char buf[] = new char[33]; + if (COMPACT_STRINGS) { + byte[] buf = new byte[33]; + boolean negative = (i < 0); + int charPos = 32; + + if (!negative) { + i = -i; + } + + while (i <= -radix) { + buf[charPos--] = (byte)digits[-(i % radix)]; + i = i / radix; + } + buf[charPos] = (byte)digits[-i]; + + if (negative) { + buf[--charPos] = '-'; + } + + return StringLatin1.newString(buf, charPos, (33 - charPos)); + } + return toStringUTF16(i, radix); + } + + private static String toStringUTF16(int i, int radix) { + byte[] buf = new byte[33 * 2]; boolean negative = (i < 0); int charPos = 32; - if (!negative) { i = -i; } - while (i <= -radix) { - buf[charPos--] = digits[-(i % radix)]; + StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]); i = i / radix; } - buf[charPos] = digits[-i]; + StringUTF16.putChar(buf, charPos, digits[-i]); if (negative) { - buf[--charPos] = '-'; + StringUTF16.putChar(buf, --charPos, '-'); } - - return new String(buf, charPos, (33 - charPos)); + return StringUTF16.newString(buf, charPos, (33 - charPos)); } /** @@ -312,12 +338,16 @@ public final class Integer extends Number implements Comparable<Integer> { // assert shift > 0 && shift <=5 : "Illegal shift value"; int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val); int chars = Math.max(((mag + (shift - 1)) / shift), 1); - char[] buf = new char[chars]; - formatUnsignedInt(val, shift, buf, 0, chars); - - // Use special constructor which takes over "buf". - return new String(buf, true); + if (COMPACT_STRINGS) { + byte[] buf = new byte[chars]; + formatUnsignedInt(val, shift, buf, 0, chars); + return new String(buf, LATIN1); + } else { + byte[] buf = new byte[chars * 2]; + formatUnsignedIntUTF16(val, shift, buf, 0, chars); + return new String(buf, UTF16); + } } /** @@ -331,7 +361,7 @@ public final class Integer extends Number implements Comparable<Integer> { * @param offset the offset in the destination buffer to start at * @param len the number of characters to write */ - static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) { + static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) { // assert shift > 0 && shift <=5 : "Illegal shift value"; // assert offset >= 0 && offset < buf.length : "illegal offset"; // assert len > 0 && (offset + len) <= buf.length : "illegal length"; @@ -344,6 +374,28 @@ public final class Integer extends Number implements Comparable<Integer> { } while (charPos > offset); } + /** byte[]/LATIN1 version */ + static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) { + int charPos = offset + len; + int radix = 1 << shift; + int mask = radix - 1; + do { + buf[--charPos] = (byte)Integer.digits[val & mask]; + val >>>= shift; + } while (charPos > offset); + } + + /** byte[]/UTF16 version */ + static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) { + int charPos = offset + len; + int radix = 1 << shift; + int mask = radix - 1; + do { + StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]); + val >>>= shift; + } while (charPos > offset); + } + static final char [] DigitTens = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', @@ -401,9 +453,15 @@ public final class Integer extends Number implements Comparable<Integer> { if (i == Integer.MIN_VALUE) return "-2147483648"; int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); - char[] buf = new char[size]; - getChars(i, size, buf); - return new String(buf, true); + if (COMPACT_STRINGS) { + byte[] buf = new byte[size]; + getChars(i, size, buf); + return new String(buf, LATIN1); + } else { + byte[] buf = new byte[size * 2]; + getCharsUTF16(i, size, buf); + return new String(buf, UTF16); + } } /** @@ -433,7 +491,41 @@ public final class Integer extends Number implements Comparable<Integer> { * * Will fail if i == Integer.MIN_VALUE */ - static void getChars(int i, int index, char[] buf) { + static void getChars(int i, int index, byte[] buf) { + int q, r; + int charPos = index; + char sign = 0; + + if (i < 0) { + sign = '-'; + i = -i; + } + + // Generate two digits per iteration + while (i >= 65536) { + q = i / 100; + // really: r = i - (q * 100); + r = i - ((q << 6) + (q << 5) + (q << 2)); + i = q; + buf [--charPos] = (byte)DigitOnes[r]; + buf [--charPos] = (byte)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; + } + if (sign != 0) { + buf [--charPos] = (byte)sign; + } + } + + static void getCharsUTF16(int i, int index, byte[] buf) { int q, r; int charPos = index; char sign = 0; @@ -449,8 +541,8 @@ public final class Integer extends Number implements Comparable<Integer> { // really: r = i - (q * 100); r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; - buf [--charPos] = DigitOnes[r]; - buf [--charPos] = DigitTens[r]; + StringUTF16.putChar(buf, --charPos, DigitOnes[r]); + StringUTF16.putChar(buf, --charPos, DigitTens[r]); } // Fall thru to fast mode for smaller numbers @@ -458,12 +550,12 @@ public final class Integer extends Number implements Comparable<Integer> { for (;;) { q = (i * 52429) >>> (16+3); r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... - buf [--charPos] = digits [r]; + StringUTF16.putChar(buf, --charPos, Integer.digits[r]); i = q; if (i == 0) break; } if (sign != 0) { - buf [--charPos] = sign; + StringUTF16.putChar(buf, --charPos, sign); } } 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 4f248d7100362ed95ed4e8e6c88ec5aed1f0cd4d..b68e2c29b7d5644f858f06191daa60c142ad3888 100644 --- a/jdk/src/java.base/share/classes/java/lang/Long.java +++ b/jdk/src/java.base/share/classes/java/lang/Long.java @@ -30,6 +30,9 @@ import java.math.*; import java.util.Objects; import jdk.internal.HotSpotIntrinsicCandidate; +import static java.lang.String.COMPACT_STRINGS; +import static java.lang.String.LATIN1; +import static java.lang.String.UTF16; /** * The {@code Long} class wraps a value of the primitive type {@code @@ -124,25 +127,46 @@ public final class Long extends Number implements Comparable<Long> { radix = 10; if (radix == 10) return toString(i); - char[] buf = new char[65]; + + if (COMPACT_STRINGS) { + byte[] buf = new byte[65]; + int charPos = 64; + boolean negative = (i < 0); + + if (!negative) { + i = -i; + } + + while (i <= -radix) { + buf[charPos--] = (byte)Integer.digits[(int)(-(i % radix))]; + i = i / radix; + } + buf[charPos] = (byte)Integer.digits[(int)(-i)]; + + if (negative) { + buf[--charPos] = '-'; + } + return StringLatin1.newString(buf, charPos, (65 - charPos)); + } + return toStringUTF16(i, radix); + } + + private static String toStringUTF16(long i, int radix) { + byte[] buf = new byte[65 * 2]; int charPos = 64; boolean negative = (i < 0); - if (!negative) { i = -i; } - while (i <= -radix) { - buf[charPos--] = Integer.digits[(int)(-(i % radix))]; + StringUTF16.putChar(buf, charPos--, Integer.digits[(int)(-(i % radix))]); i = i / radix; } - buf[charPos] = Integer.digits[(int)(-i)]; - + StringUTF16.putChar(buf, charPos, Integer.digits[(int)(-i)]); if (negative) { - buf[--charPos] = '-'; + StringUTF16.putChar(buf, --charPos, '-'); } - - return new String(buf, charPos, (65 - charPos)); + return StringUTF16.newString(buf, charPos, (65 - charPos)); } /** @@ -355,10 +379,16 @@ public final class Long extends Number implements Comparable<Long> { // assert shift > 0 && shift <=5 : "Illegal shift value"; int mag = Long.SIZE - Long.numberOfLeadingZeros(val); int chars = Math.max(((mag + (shift - 1)) / shift), 1); - char[] buf = new char[chars]; - formatUnsignedLong(val, shift, buf, 0, chars); - return new String(buf, true); + if (COMPACT_STRINGS) { + byte[] buf = new byte[chars]; + formatUnsignedLong0(val, shift, buf, 0, chars); + return new String(buf, LATIN1); + } else { + byte[] buf = new byte[chars * 2]; + formatUnsignedLong0UTF16(val, shift, buf, 0, chars); + return new String(buf, UTF16); + } } /** @@ -385,6 +415,28 @@ public final class Long extends Number implements Comparable<Long> { } while (charPos > offset); } + /** byte[]/LATIN1 version */ + static void formatUnsignedLong0(long val, int shift, byte[] buf, int offset, int len) { + int charPos = offset + len; + int radix = 1 << shift; + int mask = radix - 1; + do { + buf[--charPos] = (byte)Integer.digits[((int) val) & mask]; + val >>>= shift; + } while (charPos > offset); + } + + /** byte[]/UTF16 version */ + static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) { + int charPos = offset + len; + int radix = 1 << shift; + int mask = radix - 1; + do { + StringUTF16.putChar(buf, --charPos, Integer.digits[((int) val) & mask]); + val >>>= shift; + } while (charPos > offset); + } + /** * Returns a {@code String} object representing the specified * {@code long}. The argument is converted to signed decimal @@ -399,9 +451,15 @@ public final class Long extends Number implements Comparable<Long> { if (i == Long.MIN_VALUE) return "-9223372036854775808"; int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); - char[] buf = new char[size]; - getChars(i, size, buf); - return new String(buf, true); + if (COMPACT_STRINGS) { + byte[] buf = new byte[size]; + getChars(i, size, buf); + return new String(buf, LATIN1); + } else { + byte[] buf = new byte[size * 2]; + getCharsUTF16(i, size, buf); + return new String(buf, UTF16); + } } /** @@ -431,7 +489,54 @@ public final class Long extends Number implements Comparable<Long> { * * Will fail if i == Long.MIN_VALUE */ - static void getChars(long i, int index, char[] buf) { + static void getChars(long i, int index, byte[] buf) { + long q; + int r; + int charPos = index; + char sign = 0; + + if (i < 0) { + sign = '-'; + i = -i; + } + + // Get 2 digits/iteration using longs until quotient fits into an int + while (i > Integer.MAX_VALUE) { + q = i / 100; + // really: r = i - (q * 100); + r = (int)(i - ((q << 6) + (q << 5) + (q << 2))); + i = q; + buf[--charPos] = (byte)Integer.DigitOnes[r]; + buf[--charPos] = (byte)Integer.DigitTens[r]; + } + + // Get 2 digits/iteration using ints + int q2; + int i2 = (int)i; + while (i2 >= 65536) { + q2 = i2 / 100; + // really: r = i2 - (q * 100); + r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2)); + i2 = q2; + buf[--charPos] = (byte)Integer.DigitOnes[r]; + buf[--charPos] = (byte)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; + } + if (sign != 0) { + buf[--charPos] = (byte)sign; + } + } + + static void getCharsUTF16(long i, int index, byte[] buf) { long q; int r; int charPos = index; @@ -448,8 +553,8 @@ public final class Long extends Number implements Comparable<Long> { // really: r = i - (q * 100); r = (int)(i - ((q << 6) + (q << 5) + (q << 2))); i = q; - buf[--charPos] = Integer.DigitOnes[r]; - buf[--charPos] = Integer.DigitTens[r]; + StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]); + StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]); } // Get 2 digits/iteration using ints @@ -460,8 +565,8 @@ public final class Long extends Number implements Comparable<Long> { // really: r = i2 - (q * 100); r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2)); i2 = q2; - buf[--charPos] = Integer.DigitOnes[r]; - buf[--charPos] = Integer.DigitTens[r]; + StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]); + StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]); } // Fall thru to fast mode for smaller numbers @@ -469,12 +574,12 @@ public final class Long extends Number implements Comparable<Long> { for (;;) { q2 = (i2 * 52429) >>> (16+3); r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ... - buf[--charPos] = Integer.digits[r]; + StringUTF16.putChar(buf, --charPos, Integer.digits[r]); i2 = q2; if (i2 == 0) break; } if (sign != 0) { - buf[--charPos] = sign; + StringUTF16.putChar(buf, --charPos, sign); } } diff --git a/jdk/src/java.base/share/classes/java/lang/Process.java b/jdk/src/java.base/share/classes/java/lang/Process.java index e5077f9dcc0f1f7e77b1af871a8ec3c082925044..b537bb416d3727163a46d53f5619188e68d88f5a 100644 --- a/jdk/src/java.base/share/classes/java/lang/Process.java +++ b/jdk/src/java.base/share/classes/java/lang/Process.java @@ -83,7 +83,7 @@ import java.util.stream.Stream; * {@link #getPid() process id}, * {@link #info() information about the process}, * {@link #children() direct children}, and - * {@link #allChildren() direct and indirect children} of the process. + * {@link #descendants() direct children plus descendants of those children} of the process. * Delegating to the underlying Process or ProcessHandle is typically * easiest and most efficient. * @@ -351,7 +351,7 @@ public abstract class Process { * The {@link java.util.concurrent.CompletableFuture} provides the ability * to trigger dependent functions or actions that may be run synchronously * or asynchronously upon process termination. - * When the process terminates the CompletableFuture is + * When the process has terminated the CompletableFuture is * {@link java.util.concurrent.CompletableFuture#complete completed} regardless * of the exit status of the process. * <p> @@ -362,9 +362,6 @@ public abstract class Process { * {@link java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling} * the CompletableFuture does not affect the Process. * <p> - * If the process is {@link #isAlive not alive} the {@link CompletableFuture} - * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}. - * <p> * Processes returned from {@link ProcessBuilder#start} override the * default implementation to provide an efficient mechanism to wait * for process exit. @@ -406,6 +403,9 @@ public abstract class Process { * return delegate.onExit().thenApply(p -> this); * } * }</pre> + * @apiNote + * The process may be observed to have terminated with {@link #isAlive} + * before the ComputableFuture is completed and dependent actions are invoked. * * @return a new {@code CompletableFuture<Process>} for the Process * @@ -464,7 +464,7 @@ public abstract class Process { * {@link java.lang.UnsupportedOperationException} and performs no other action. * Subclasses should override this method to provide a ProcessHandle for the * process. The methods {@link #getPid}, {@link #info}, {@link #children}, - * and {@link #allChildren}, unless overridden, operate on the ProcessHandle. + * and {@link #descendants}, unless overridden, operate on the ProcessHandle. * * @return Returns a ProcessHandle for the Process * @throws UnsupportedOperationException if the Process implementation @@ -481,9 +481,8 @@ public abstract class Process { /** * Returns a snapshot of information about the process. * - * <p> An {@link ProcessHandle.Info} instance has various accessor methods - * that return information about the process, if the process is alive and - * the information is available, otherwise {@code null} is returned. + * <p> A {@link ProcessHandle.Info} instance has accessor methods + * that return information about the process if it is available. * * @implSpec * This implementation returns information about the process as: @@ -524,9 +523,9 @@ public abstract class Process { } /** - * Returns a snapshot of the direct and indirect children of the process. - * An indirect child is one whose parent is either a direct child or - * another indirect child. + * Returns a snapshot of the descendants of the process. + * The descendants of a process are the children of the process + * plus the descendants of those children, recursively. * Typically, a process that is {@link #isAlive not alive} has no children. * <p> * <em>Note that processes are created and terminate asynchronously. @@ -535,18 +534,18 @@ public abstract class Process { * * @implSpec * This implementation returns all children as: - * {@link #toHandle toHandle().allChildren()}. + * {@link #toHandle toHandle().descendants()}. * - * @return a sequential Stream of ProcessHandles for processes that are - * direct and indirect children of the process + * @return a sequential Stream of ProcessHandles for processes that + * are descendants of the process * @throws UnsupportedOperationException if the Process implementation * does not support this operation * @throws SecurityException if a security manager has been installed and * it denies RuntimePermission("manageProcess") * @since 1.9 */ - public Stream<ProcessHandle> allChildren() { - return toHandle().allChildren(); + public Stream<ProcessHandle> descendants() { + return toHandle().descendants(); } diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java index 95d77fe68ca8781069308f3e1c55802642af7683..a7e650fee047f665f8086ed3f804709e50f1ffeb 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java @@ -54,7 +54,7 @@ import java.util.stream.Stream; * Each ProcessHandle identifies and allows control of a process in the native * system. ProcessHandles are returned from the factory methods {@link #current()}, * {@link #of(long)}, - * {@link #children}, {@link #allChildren}, {@link #parent()} and + * {@link #children}, {@link #descendants}, {@link #parent()} and * {@link #allProcesses()}. * <p> * The {@link Process} instances created by {@link ProcessBuilder} can be queried @@ -164,21 +164,21 @@ public interface ProcessHandle extends Comparable<ProcessHandle> { Stream<ProcessHandle> children(); /** - * Returns a snapshot of the current direct and indirect children of the process. - * An indirect child is one whose parent is either a direct child or - * another indirect child. + * Returns a snapshot of the descendants of the process. + * The descendants of a process are the children of the process + * plus the descendants of those children, recursively. * Typically, a process that is {@link #isAlive not alive} has no children. * <p> * <em>Note that processes are created and terminate asynchronously. * There is no guarantee that a process is {@link #isAlive alive}. * </em> * - * @return a sequential Stream of ProcessHandles for processes that are - * direct and indirect children of the process + * @return a sequential Stream of ProcessHandles for processes that + * are descendants of the process * @throws SecurityException if a security manager has been installed and * it denies RuntimePermission("manageProcess") */ - Stream<ProcessHandle> allChildren(); + Stream<ProcessHandle> descendants(); /** * Returns a snapshot of all processes visible to the current process. @@ -201,9 +201,8 @@ public interface ProcessHandle extends Comparable<ProcessHandle> { /** * Returns a snapshot of information about the process. * - * <p> An {@code Info} instance has various accessor methods that return - * information about the process, if the process is alive and the - * information is available. + * <p> A {@link ProcessHandle.Info} instance has accessor methods that return + * information about the process if it is available. * * @return a snapshot of information about the process, always non-null */ @@ -288,7 +287,7 @@ public interface ProcessHandle extends Comparable<ProcessHandle> { * The {@link java.util.concurrent.CompletableFuture} provides the ability * to trigger dependent functions or actions that may be run synchronously * or asynchronously upon process termination. - * When the process terminates the CompletableFuture is + * When the process has terminated the CompletableFuture is * {@link java.util.concurrent.CompletableFuture#complete completed} regardless * of the exit status of the process. * The {@code onExit} method can be called multiple times to invoke @@ -300,9 +299,9 @@ public interface ProcessHandle extends Comparable<ProcessHandle> { * {@link java.util.concurrent.Future#get() wait} for it to terminate. * {@link java.util.concurrent.Future#cancel(boolean) Cancelling} * the CompleteableFuture does not affect the Process. - * <p> - * If the process is {@link #isAlive not alive} the {@link CompletableFuture} - * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}. + * @apiNote + * The process may be observed to have terminated with {@link #isAlive} + * before the ComputableFuture is completed and dependent actions are invoked. * * @return a new {@code CompletableFuture<ProcessHandle>} for the ProcessHandle * 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 b3d03683e4a53c2d71505f6fbfa49835924076de..92b175b09574a889ec22ca1e489b6d40d9682667 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java @@ -389,7 +389,7 @@ final class ProcessHandleImpl implements ProcessHandle { } @Override - public Stream<ProcessHandle> allChildren() { + public Stream<ProcessHandle> descendants() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("manageProcess")); diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java index ce4262eee19cd678b1685596f5195e92cad44694..4d4ab358b9f685e32bdd90f04e33fe7cb5451f9f 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -36,7 +36,6 @@ import java.util.Locale; import java.util.Objects; import java.util.Spliterator; import java.util.StringJoiner; -import java.util.function.IntConsumer; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -119,8 +118,19 @@ import jdk.internal.HotSpotIntrinsicCandidate; public final class String implements java.io.Serializable, Comparable<String>, CharSequence { + /** The value is used for character storage. */ - private final char value[]; + private final byte[] value; + + /** + * The identifier of the encoding used to encode the bytes in + * {@code value}. The supported values in this implementation are + * + * LATIN1 + * UTF16 + * + */ + private final byte coder; /** Cache the hash code for the string */ private int hash; // Default to 0 @@ -128,6 +138,49 @@ public final class String /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -6849794470754667710L; + /** + * If String compaction is disabled, the bytes in {@code value} are + * always encoded in UTF16. + * + * For methods with several possible implementation paths, when String + * compaction is disabled, only one code path is taken. + * + * The instance field value is generally opaque to optimizing JIT + * compilers. Therefore, in performance-sensitive place, an explicit + * check of the static boolean {@code COMPACT_STRINGS} is done first + * before checking the {@code coder} field since the static boolean + * {@code COMPACT_STRINGS} would be constant folded away by an + * optimizing JIT compiler. The idioms for these cases are as follows. + * + * For code such as: + * + * if (coder == LATIN1) { ... } + * + * can be written more optimally as + * + * if (coder() == LATIN1) { ... } + * + * or: + * + * if (COMPACT_STRINGS && coder == LATIN1) { ... } + * + * An optimizing JIT compiler can fold the above conditional as: + * + * COMPACT_STRINGS == true => if (coder == LATIN1) { ... } + * COMPACT_STRINGS == false => if (false) { ... } + * + * @implNote + * The actual value for this field is injected by JVM. The static + * initialization block is used to set the value here to communicate + * that this static final field is not statically foldable, and to + * avoid any possible circular dependency during vm initialization. + */ + static final boolean COMPACT_STRINGS; + + static { + COMPACT_STRINGS = true; + } + /** * Class String is special cased within the Serialization Stream Protocol. * @@ -145,6 +198,7 @@ public final class String */ public String() { this.value = "".value; + this.coder = "".coder; } /** @@ -160,6 +214,7 @@ public final class String @HotSpotIntrinsicCandidate public String(String original) { this.value = original.value; + this.coder = original.coder; this.hash = original.hash; } @@ -173,7 +228,7 @@ public final class String * The initial value of the string */ public String(char value[]) { - this.value = Arrays.copyOf(value, value.length); + this(value, 0, value.length, null); } /** @@ -198,23 +253,12 @@ public final class String * {@code offset} is greater than {@code value.length - count} */ public String(char value[], int offset, int count) { - if (offset < 0) { - throw new StringIndexOutOfBoundsException(offset); - } - if (count <= 0) { - if (count < 0) { - throw new StringIndexOutOfBoundsException(count); - } - if (offset <= value.length) { - this.value = "".value; - return; - } - } - // Note: offset or count might be near -1>>>1. - if (offset > value.length - count) { - throw new StringIndexOutOfBoundsException(offset + count); - } - this.value = Arrays.copyOfRange(value, offset, offset + count); + this(value, offset, count, rangeCheck(value, offset, count)); + } + + private static Void rangeCheck(char[] value, int offset, int count) { + checkBoundsOffCount(offset, count, value.length); + return null; } /** @@ -246,48 +290,22 @@ public final class String * @since 1.5 */ public String(int[] codePoints, int offset, int count) { - if (offset < 0) { - throw new StringIndexOutOfBoundsException(offset); - } - if (count <= 0) { - if (count < 0) { - throw new StringIndexOutOfBoundsException(count); - } - if (offset <= codePoints.length) { - this.value = "".value; + checkBoundsOffCount(offset, count, codePoints.length); + if (count == 0) { + this.value = "".value; + this.coder = "".coder; + return; + } + if (COMPACT_STRINGS) { + byte[] val = StringLatin1.toBytes(codePoints, offset, count); + if (val != null) { + this.coder = LATIN1; + this.value = val; return; } } - // Note: offset or count might be near -1>>>1. - if (offset > codePoints.length - count) { - throw new StringIndexOutOfBoundsException(offset + count); - } - - final int end = offset + count; - - // Pass 1: Compute precise size of char[] - int n = count; - for (int i = offset; i < end; i++) { - int c = codePoints[i]; - if (Character.isBmpCodePoint(c)) - continue; - else if (Character.isValidCodePoint(c)) - n++; - else throw new IllegalArgumentException(Integer.toString(c)); - } - - // Pass 2: Allocate and fill in char[] - final char[] v = new char[n]; - - for (int i = offset, j = 0; i < end; i++, j++) { - int c = codePoints[i]; - if (Character.isBmpCodePoint(c)) - v[j] = (char)c; - else - Character.toSurrogates(c, v, j++); - } - - this.value = v; + this.coder = UTF16; + this.value = StringUTF16.toBytes(codePoints, offset, count); } /** @@ -332,20 +350,24 @@ public final class String */ @Deprecated public String(byte ascii[], int hibyte, int offset, int count) { - checkBounds(ascii, offset, count); - char[] value = new char[count]; - - if (hibyte == 0) { - for (int i = count; i-- > 0;) { - value[i] = (char)(ascii[i + offset] & 0xff); - } + checkBoundsOffCount(offset, count, ascii.length); + if (count == 0) { + this.value = "".value; + this.coder = "".coder; + return; + } + if (COMPACT_STRINGS && (byte)hibyte == 0) { + this.value = Arrays.copyOfRange(ascii, offset, offset + count); + this.coder = LATIN1; } else { hibyte <<= 8; - for (int i = count; i-- > 0;) { - value[i] = (char)(hibyte | (ascii[i + offset] & 0xff)); + byte[] val = StringUTF16.newBytesFor(count); + for (int i = 0; i < count; i++) { + StringUTF16.putChar(val, i, hibyte | (ascii[offset++] & 0xff)); } + this.value = val; + this.coder = UTF16; } - this.value = value; } /** @@ -383,19 +405,6 @@ public final class String this(ascii, hibyte, 0, ascii.length); } - /* Common private utility method used to bounds check the byte array - * and requested offset & length values used by the String(byte[],..) - * constructors. - */ - private static void checkBounds(byte[] bytes, int offset, int length) { - if (length < 0) - throw new StringIndexOutOfBoundsException(length); - if (offset < 0) - throw new StringIndexOutOfBoundsException(offset); - if (offset > bytes.length - length) - throw new StringIndexOutOfBoundsException(offset + length); - } - /** * Constructs a new {@code String} by decoding the specified subarray of * bytes using the specified charset. The length of the new {@code String} @@ -433,8 +442,11 @@ public final class String throws UnsupportedEncodingException { if (charsetName == null) throw new NullPointerException("charsetName"); - checkBounds(bytes, offset, length); - this.value = StringCoding.decode(charsetName, bytes, offset, length); + checkBoundsOffCount(offset, length, bytes.length); + StringCoding.Result ret = + StringCoding.decode(charsetName, bytes, offset, length); + this.value = ret.value; + this.coder = ret.coder; } /** @@ -470,8 +482,11 @@ public final class String public String(byte bytes[], int offset, int length, Charset charset) { if (charset == null) throw new NullPointerException("charset"); - checkBounds(bytes, offset, length); - this.value = StringCoding.decode(charset, bytes, offset, length); + checkBoundsOffCount(offset, length, bytes.length); + StringCoding.Result ret = + StringCoding.decode(charset, bytes, offset, length); + this.value = ret.value; + this.coder = ret.coder; } /** @@ -553,8 +568,10 @@ public final class String * @since 1.1 */ public String(byte bytes[], int offset, int length) { - checkBounds(bytes, offset, length); - this.value = StringCoding.decode(bytes, offset, length); + checkBoundsOffCount(offset, length, bytes.length); + StringCoding.Result ret = StringCoding.decode(bytes, offset, length); + this.value = ret.value; + this.coder = ret.coder; } /** @@ -587,9 +604,7 @@ public final class String * A {@code StringBuffer} */ public String(StringBuffer buffer) { - synchronized(buffer) { - this.value = Arrays.copyOf(buffer.getValue(), buffer.length()); - } + this(buffer.toString()); } /** @@ -608,18 +623,20 @@ public final class String * @since 1.5 */ public String(StringBuilder builder) { - this.value = Arrays.copyOf(builder.getValue(), builder.length()); + this(builder, null); } - /* + /* * Package private constructor which shares value array for speed. * this constructor is always expected to be called with share==true. * a separate constructor is needed because we already have a public * String(char[]) constructor that makes a copy of the given char[]. */ - String(char[] value, boolean share) { + // TBD: this is kept for package internal use (Thread/System), + // should be removed if they all have a byte[] version + String(char[] val, boolean share) { // assert share : "unshared not supported"; - this.value = value; + this(val, 0, val.length, null); } /** @@ -631,7 +648,7 @@ public final class String * object. */ public int length() { - return value.length; + return value.length >> coder(); } /** @@ -665,10 +682,11 @@ public final class String * string. */ public char charAt(int index) { - if ((index < 0) || (index >= value.length)) { - throw new StringIndexOutOfBoundsException(index); + if (isLatin1()) { + return StringLatin1.charAt(value, index); + } else { + return StringUTF16.charAt(value, index); } - return value[index]; } /** @@ -694,10 +712,13 @@ public final class String * @since 1.5 */ public int codePointAt(int index) { - if ((index < 0) || (index >= value.length)) { - throw new StringIndexOutOfBoundsException(index); + if (isLatin1()) { + checkIndex(index, value.length); + return value[index] & 0xff; } - return Character.codePointAtImpl(value, index, value.length); + int length = value.length >> 1; + checkIndex(index, length); + return StringUTF16.codePointAt(value, index, length); } /** @@ -724,10 +745,13 @@ public final class String */ public int codePointBefore(int index) { int i = index - 1; - if ((i < 0) || (i >= value.length)) { + if (i < 0 || i >= length()) { throw new StringIndexOutOfBoundsException(index); } - return Character.codePointBeforeImpl(value, index, 0); + if (isLatin1()) { + return (value[i] & 0xff); + } + return StringUTF16.codePointBefore(value, index); } /** @@ -752,10 +776,14 @@ public final class String * @since 1.5 */ public int codePointCount(int beginIndex, int endIndex) { - if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) { + if (beginIndex < 0 || beginIndex > endIndex || + endIndex > length()) { throw new IndexOutOfBoundsException(); } - return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex); + if (isLatin1()) { + return endIndex - beginIndex; + } + return StringUTF16.codePointCount(value, beginIndex, endIndex); } /** @@ -779,19 +807,10 @@ public final class String * @since 1.5 */ public int offsetByCodePoints(int index, int codePointOffset) { - if (index < 0 || index > value.length) { + if (index < 0 || index > length()) { throw new IndexOutOfBoundsException(); } - return Character.offsetByCodePointsImpl(value, 0, value.length, - index, codePointOffset); - } - - /** - * Copy characters from this string into dst starting at dstBegin. - * This method doesn't perform any range checking. - */ - void getChars(char dst[], int dstBegin) { - System.arraycopy(value, 0, dst, dstBegin, value.length); + return Character.offsetByCodePoints(this, index, codePointOffset); } /** @@ -825,16 +844,13 @@ public final class String * {@code dst.length}</ul> */ public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { - if (srcBegin < 0) { - throw new StringIndexOutOfBoundsException(srcBegin); - } - if (srcEnd > value.length) { - throw new StringIndexOutOfBoundsException(srcEnd); - } - if (srcBegin > srcEnd) { - throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); + checkBoundsBeginEnd(srcBegin, srcEnd, length()); + checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length); + if (isLatin1()) { + StringLatin1.getChars(value, srcBegin, srcEnd, dst, dstBegin); + } else { + StringUTF16.getChars(value, srcBegin, srcEnd, dst, dstBegin); } - System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); } /** @@ -882,24 +898,13 @@ public final class String */ @Deprecated public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) { - if (srcBegin < 0) { - throw new StringIndexOutOfBoundsException(srcBegin); - } - if (srcEnd > value.length) { - throw new StringIndexOutOfBoundsException(srcEnd); - } - if (srcBegin > srcEnd) { - throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); - } + checkBoundsBeginEnd(srcBegin, srcEnd, length()); Objects.requireNonNull(dst); - - int j = dstBegin; - int n = srcEnd; - int i = srcBegin; - char[] val = value; /* avoid getfield opcode */ - - while (i < n) { - dst[j++] = (byte)val[i++]; + checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length); + if (isLatin1()) { + StringLatin1.getBytes(value, srcBegin, srcEnd, dst, dstBegin); + } else { + StringUTF16.getBytes(value, srcBegin, srcEnd, dst, dstBegin); } } @@ -926,7 +931,7 @@ public final class String public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { if (charsetName == null) throw new NullPointerException(); - return StringCoding.encode(charsetName, value, 0, value.length); + return StringCoding.encode(charsetName, coder(), value); } /** @@ -949,8 +954,8 @@ public final class String */ public byte[] getBytes(Charset charset) { if (charset == null) throw new NullPointerException(); - return StringCoding.encode(charset, value, 0, value.length); - } + return StringCoding.encode(charset, coder(), value); + } /** * Encodes this {@code String} into a sequence of bytes using the @@ -966,7 +971,7 @@ public final class String * @since 1.1 */ public byte[] getBytes() { - return StringCoding.encode(value, 0, value.length); + return StringCoding.encode(coder(), value); } /** @@ -987,23 +992,15 @@ public final class String * @see #compareTo(String) * @see #equalsIgnoreCase(String) */ - @HotSpotIntrinsicCandidate public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { - char[] v1 = value; - char[] v2 = ((String)anObject).value; - int n = v1.length; - if (n == v2.length) { - int i = 0; - while (n-- != 0) { - if (v1[i] != v2[i]) - return false; - i++; - } - return true; + String aString = (String)anObject; + if (coder() == aString.coder()) { + return isLatin1() ? StringLatin1.equals(value, aString.value) + : StringUTF16.equals(value, aString.value); } } return false; @@ -1032,16 +1029,28 @@ public final class String } private boolean nonSyncContentEquals(AbstractStringBuilder sb) { - char[] v1 = value; - char[] v2 = sb.getValue(); - int n = v1.length; - if (n != sb.length()) { + int len = length(); + if (len != sb.length()) { return false; } - for (int i = 0; i < n; i++) { - if (v1[i] != v2[i]) { + byte v1[] = value; + byte v2[] = sb.getValue(); + if (coder() == sb.getCoder()) { + int n = v1.length; + for (int i = 0; i < n; i++) { + if (v1[i] != v2[i]) { + return false; + } + } + } else { + if (!isLatin1()) { // utf16 str and latin1 abs can never be "equal" return false; } + for (int i = 0; i < len; i++) { + if ((char)(v1[i] & 0xff) != StringUTF16.getChar(v2, i)) { + return false; + } + } } return true; } @@ -1081,14 +1090,22 @@ public final class String return equals(cs); } // Argument is a generic CharSequence - char[] v1 = value; - int n = v1.length; - if (n != cs.length()) { + int n = cs.length(); + if (n != length()) { return false; } - for (int i = 0; i < n; i++) { - if (v1[i] != cs.charAt(i)) { - return false; + byte[] val = this.value; + if (isLatin1()) { + for (int i = 0; i < n; i++) { + if ((val[i] & 0xff) != cs.charAt(i)) { + return false; + } + } + } else { + for (int i = 0; i < n; i++) { + if (StringUTF16.getChar(val, i) != cs.charAt(i)) { + return false; + } } } return true; @@ -1125,8 +1142,8 @@ public final class String public boolean equalsIgnoreCase(String anotherString) { return (this == anotherString) ? true : (anotherString != null) - && (anotherString.value.length == value.length) - && regionMatches(true, 0, anotherString, 0, value.length); + && (anotherString.length() == length()) + && regionMatches(true, 0, anotherString, 0, length()); } /** @@ -1173,23 +1190,16 @@ public final class String * value greater than {@code 0} if this string is * lexicographically greater than the string argument. */ - @HotSpotIntrinsicCandidate public int compareTo(String anotherString) { - char[] v1 = value; - char[] v2 = anotherString.value; - int len1 = v1.length; - int len2 = v2.length; - int lim = Math.min(len1, len2); - - for (int k = 0; k < lim; k++) { - char c1 = v1[k]; - char c2 = v2[k]; - if (c1 != c2) { - return c1 - c2; - } + byte v1[] = value; + byte v2[] = anotherString.value; + if (coder() == anotherString.coder()) { + return isLatin1() ? StringLatin1.compareTo(v1, v2) + : StringUTF16.compareTo(v1, v2); } - return len1 - len2; - } + return isLatin1() ? StringLatin1.compareToUTF16(v1, v2) + : StringUTF16.compareToLatin1(v1, v2); + } /** * A Comparator that orders {@code String} objects as by @@ -1210,12 +1220,18 @@ public final class String private static final long serialVersionUID = 8575799808933029326L; public int compare(String s1, String s2) { + byte v1[] = s1.value; + byte v2[] = s2.value; int n1 = s1.length(); int n2 = s2.length(); + boolean s1IsLatin1 = s1.isLatin1(); + boolean s2IsLatin1 = s2.isLatin1(); int min = Math.min(n1, n2); for (int i = 0; i < min; i++) { - char c1 = s1.charAt(i); - char c2 = s2.charAt(i); + char c1 = s1IsLatin1 ? StringLatin1.getChar(v1, i) + : StringUTF16.getChar(v1, i); + char c2 = s2IsLatin1 ? StringLatin1.getChar(v2, i) + : StringUTF16.getChar(v2, i); if (c1 != c2) { c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); @@ -1294,21 +1310,41 @@ public final class String * exactly matches the specified subregion of the string argument; * {@code false} otherwise. */ - public boolean regionMatches(int toffset, String other, int ooffset, - int len) { - char[] ta = value; - int to = toffset; - char[] pa = other.value; - int po = ooffset; + public boolean regionMatches(int toffset, String other, int ooffset, int len) { + byte tv[] = value; + byte ov[] = other.value; // Note: toffset, ooffset, or len might be near -1>>>1. - if ((ooffset < 0) || (toffset < 0) - || (toffset > (long)ta.length - len) - || (ooffset > (long)pa.length - len)) { + if ((ooffset < 0) || (toffset < 0) || + (toffset > (long)length() - len) || + (ooffset > (long)other.length() - len)) { return false; } - while (len-- > 0) { - if (ta[to++] != pa[po++]) { - return false; + if (coder() == other.coder()) { + if (!isLatin1() && (len > 0)) { + toffset = toffset << 1; + ooffset = ooffset << 1; + len = len << 1; + } + while (len-- > 0) { + if (tv[toffset++] != ov[ooffset++]) { + return false; + } + } + } else { + if (coder() == LATIN1) { + while (len-- > 0) { + if (StringLatin1.getChar(tv, toffset++) != + StringUTF16.getChar(ov, ooffset++)) { + return false; + } + } + } else { + while (len-- > 0) { + if (StringUTF16.getChar(tv, toffset++) != + StringLatin1.getChar(ov, ooffset++)) { + return false; + } + } } } return true; @@ -1366,43 +1402,25 @@ public final class String */ public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) { - char[] ta = value; - int to = toffset; - char[] pa = other.value; - int po = ooffset; + if (!ignoreCase) { + return regionMatches(toffset, other, ooffset, len); + } // Note: toffset, ooffset, or len might be near -1>>>1. if ((ooffset < 0) || (toffset < 0) - || (toffset > (long)ta.length - len) - || (ooffset > (long)pa.length - len)) { + || (toffset > (long)length() - len) + || (ooffset > (long)other.length() - len)) { return false; } - while (len-- > 0) { - char c1 = ta[to++]; - char c2 = pa[po++]; - if (c1 == c2) { - continue; - } - if (ignoreCase) { - // If characters don't match but case may be ignored, - // try converting both characters to uppercase. - // If the results match, then the comparison scan should - // continue. - char u1 = Character.toUpperCase(c1); - char u2 = Character.toUpperCase(c2); - if (u1 == u2) { - continue; - } - // Unfortunately, conversion to uppercase does not work properly - // for the Georgian alphabet, which has strange rules about case - // conversion. So we need to make one last check before - // exiting. - if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { - continue; - } - } - return false; + byte tv[] = value; + byte ov[] = other.value; + if (coder() == other.coder()) { + return isLatin1() + ? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len) + : StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len); } - return true; + return isLatin1() + ? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len) + : StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len); } /** @@ -1423,19 +1441,31 @@ public final class String * </pre> */ public boolean startsWith(String prefix, int toffset) { - char[] ta = value; - int to = toffset; - char[] pa = prefix.value; - int po = 0; - int pc = pa.length; // Note: toffset might be near -1>>>1. - if ((toffset < 0) || (toffset > ta.length - pc)) { + if (toffset < 0 || toffset > length() - prefix.length()) { return false; } - while (--pc >= 0) { - if (ta[to++] != pa[po++]) { + byte ta[] = value; + byte pa[] = prefix.value; + int po = 0; + int pc = pa.length; + if (coder() == prefix.coder()) { + int to = isLatin1() ? toffset : toffset << 1; + while (po < pc) { + if (ta[to++] != pa[po++]) { + return false; + } + } + } else { + if (isLatin1()) { // && pcoder == UTF16 return false; } + // coder == UTF16 && pcoder == LATIN1) + while (po < pc) { + if (StringUTF16.getChar(ta, toffset++) != (pa[po++] & 0xff)) { + return false; + } + } } return true; } @@ -1469,7 +1499,7 @@ public final class String * as determined by the {@link #equals(Object)} method. */ public boolean endsWith(String suffix) { - return startsWith(suffix, value.length - suffix.value.length); + return startsWith(suffix, length() - suffix.length()); } /** @@ -1486,16 +1516,11 @@ public final class String * @return a hash code value for this object. */ public int hashCode() { - int h = hash; - if (h == 0) { - for (char v : value) { - h = 31 * h + v; - } - if (h != 0) { - hash = h; - } + if (hash == 0 && value.length > 0) { + hash = isLatin1() ? StringLatin1.hashCode(value) + : StringUTF16.hashCode(value); } - return h; + return hash; } /** @@ -1566,45 +1591,8 @@ public final class String * if the character does not occur. */ public int indexOf(int ch, int fromIndex) { - final int max = value.length; - if (fromIndex < 0) { - fromIndex = 0; - } else if (fromIndex >= max) { - // Note: fromIndex might be near -1>>>1. - return -1; - } - - if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { - // handle most cases here (ch is a BMP code point or a - // negative value (invalid code point)) - final char[] value = this.value; - for (int i = fromIndex; i < max; i++) { - if (value[i] == ch) { - return i; - } - } - return -1; - } else { - return indexOfSupplementary(ch, fromIndex); - } - } - - /** - * Handles (rare) calls of indexOf with a supplementary character. - */ - private int indexOfSupplementary(int ch, int fromIndex) { - if (Character.isValidCodePoint(ch)) { - final char[] value = this.value; - final char hi = Character.highSurrogate(ch); - final char lo = Character.lowSurrogate(ch); - final int max = value.length - 1; - for (int i = fromIndex; i < max; i++) { - if (value[i] == hi && value[i + 1] == lo) { - return i; - } - } - } - return -1; + return isLatin1() ? StringLatin1.indexOf(value, ch, fromIndex) + : StringUTF16.indexOf(value, ch, fromIndex); } /** @@ -1631,7 +1619,7 @@ public final class String * {@code -1} if the character does not occur. */ public int lastIndexOf(int ch) { - return lastIndexOf(ch, value.length - 1); + return lastIndexOf(ch, length() - 1); } /** @@ -1669,38 +1657,8 @@ public final class String * if the character does not occur before that point. */ public int lastIndexOf(int ch, int fromIndex) { - if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { - // handle most cases here (ch is a BMP code point or a - // negative value (invalid code point)) - final char[] value = this.value; - int i = Math.min(fromIndex, value.length - 1); - for (; i >= 0; i--) { - if (value[i] == ch) { - return i; - } - } - return -1; - } else { - return lastIndexOfSupplementary(ch, fromIndex); - } - } - - /** - * Handles (rare) calls of lastIndexOf with a supplementary character. - */ - private int lastIndexOfSupplementary(int ch, int fromIndex) { - if (Character.isValidCodePoint(ch)) { - final char[] value = this.value; - char hi = Character.highSurrogate(ch); - char lo = Character.lowSurrogate(ch); - int i = Math.min(fromIndex, value.length - 2); - for (; i >= 0; i--) { - if (value[i] == hi && value[i + 1] == lo) { - return i; - } - } - } - return -1; + return isLatin1() ? StringLatin1.lastIndexOf(value, ch, fromIndex) + : StringUTF16.lastIndexOf(value, ch, fromIndex); } /** @@ -1717,9 +1675,15 @@ public final class String * @return the index of the first occurrence of the specified substring, * or {@code -1} if there is no such occurrence. */ - @HotSpotIntrinsicCandidate public int indexOf(String str) { - return indexOf(str, 0); + if (coder() == str.coder()) { + return isLatin1() ? StringLatin1.indexOf(value, str.value) + : StringUTF16.indexOf(value, str.value); + } + if (coder() == LATIN1) { // str.coder == UTF16 + return -1; + } + return StringUTF16.indexOfLatin1(value, str.value); } /** @@ -1740,8 +1704,7 @@ public final class String * or {@code -1} if there is no such occurrence. */ public int indexOf(String str, int fromIndex) { - return indexOf(value, 0, value.length, - str.value, 0, str.value.length, fromIndex); + return indexOf(value, coder(), length(), str, fromIndex); } /** @@ -1749,68 +1712,38 @@ public final class String * source is the character array being searched, and the target * is the string being searched for. * - * @param source the characters being searched. - * @param sourceOffset offset of the source string. - * @param sourceCount count of the source string. - * @param target the characters being searched for. - * @param fromIndex the index to begin searching from. + * @param src the characters being searched. + * @param srcCoder the coder of the source string. + * @param srcCount length of the source string. + * @param tgtStr the characters being searched for. + * @param fromIndex the index to begin searching from. */ - static int indexOf(char[] source, int sourceOffset, int sourceCount, - String target, int fromIndex) { - return indexOf(source, sourceOffset, sourceCount, - target.value, 0, target.value.length, - fromIndex); - } + static int indexOf(byte[] src, byte srcCoder, int srcCount, + String tgtStr, int fromIndex) { - /** - * Code shared by String and StringBuffer to do searches. The - * source is the character array being searched, and the target - * is the string being searched for. - * - * @param source the characters being searched. - * @param sourceOffset offset of the source string. - * @param sourceCount count of the source string. - * @param target the characters being searched for. - * @param targetOffset offset of the target string. - * @param targetCount count of the target string. - * @param fromIndex the index to begin searching from. - */ - static int indexOf(char[] source, int sourceOffset, int sourceCount, - char[] target, int targetOffset, int targetCount, - int fromIndex) { - if (fromIndex >= sourceCount) { - return (targetCount == 0 ? sourceCount : -1); + byte[] tgt = tgtStr.value; + byte tgtCoder = tgtStr.coder(); + int tgtCount = tgtStr.length(); + + if (fromIndex >= srcCount) { + return (tgtCount == 0 ? srcCount : -1); } if (fromIndex < 0) { fromIndex = 0; } - if (targetCount == 0) { + if (tgtCount == 0) { return fromIndex; } - - char first = target[targetOffset]; - int max = sourceOffset + (sourceCount - targetCount); - - for (int i = sourceOffset + fromIndex; i <= max; i++) { - /* Look for first character. */ - if (source[i] != first) { - while (++i <= max && source[i] != first); - } - - /* Found first character, now look at the rest of v2 */ - if (i <= max) { - int j = i + 1; - int end = j + targetCount - 1; - for (int k = targetOffset + 1; j < end && source[j] - == target[k]; j++, k++); - - if (j == end) { - /* Found whole string. */ - return i - sourceOffset; - } - } + if (srcCoder == tgtCoder) { + return srcCoder == LATIN1 + ? StringLatin1.indexOf(src, srcCount, tgt, tgtCount, fromIndex) + : StringUTF16.indexOf(src, srcCount, tgt, tgtCount, fromIndex); } - return -1; + if (srcCoder == LATIN1) { // && tgtCoder == UTF16 + return -1; + } + // srcCoder == UTF16 && tgtCoder == LATIN1) { + return StringUTF16.indexOfLatin1(src, srcCount, tgt, tgtCount, fromIndex); } /** @@ -1829,7 +1762,7 @@ public final class String * or {@code -1} if there is no such occurrence. */ public int lastIndexOf(String str) { - return lastIndexOf(str, value.length); + return lastIndexOf(str, length()); } /** @@ -1850,8 +1783,7 @@ public final class String * or {@code -1} if there is no such occurrence. */ public int lastIndexOf(String str, int fromIndex) { - return lastIndexOf(value, 0, value.length, - str.value, 0, str.value.length, fromIndex); + return lastIndexOf(value, coder(), length(), str, fromIndex); } /** @@ -1859,40 +1791,22 @@ public final class String * source is the character array being searched, and the target * is the string being searched for. * - * @param source the characters being searched. - * @param sourceOffset offset of the source string. - * @param sourceCount count of the source string. - * @param target the characters being searched for. - * @param fromIndex the index to begin searching from. - */ - static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, - String target, int fromIndex) { - return lastIndexOf(source, sourceOffset, sourceCount, - target.value, 0, target.value.length, - fromIndex); - } - - /** - * Code shared by String and StringBuffer to do searches. The - * source is the character array being searched, and the target - * is the string being searched for. - * - * @param source the characters being searched. - * @param sourceOffset offset of the source string. - * @param sourceCount count of the source string. - * @param target the characters being searched for. - * @param targetOffset offset of the target string. - * @param targetCount count of the target string. - * @param fromIndex the index to begin searching from. - */ - static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, - char[] target, int targetOffset, int targetCount, - int fromIndex) { + * @param src the characters being searched. + * @param srcCoder coder handles the mapping between bytes/chars + * @param srcCount count of the source string. + * @param tgt the characters being searched for. + * @param fromIndex the index to begin searching from. + */ + static int lastIndexOf(byte[] src, byte srcCoder, int srcCount, + String tgtStr, int fromIndex) { + byte[] tgt = tgtStr.value; + byte tgtCoder = tgtStr.coder(); + int tgtCount = tgtStr.length(); /* * Check arguments; return immediately where possible. For * consistency, don't check for null str. */ - int rightIndex = sourceCount - targetCount; + int rightIndex = srcCount - tgtCount; if (fromIndex < 0) { return -1; } @@ -1900,34 +1814,41 @@ public final class String fromIndex = rightIndex; } /* Empty string always matches. */ - if (targetCount == 0) { + if (tgtCount == 0) { return fromIndex; } - - int strLastIndex = targetOffset + targetCount - 1; - char strLastChar = target[strLastIndex]; - int min = sourceOffset + targetCount - 1; + if (srcCoder == tgtCoder) { + return srcCoder == LATIN1 + ? StringLatin1.lastIndexOf(src, srcCount, tgt, tgtCount, fromIndex) + : StringUTF16.lastIndexOf(src, srcCount, tgt, tgtCount, fromIndex); + } + if (srcCoder == LATIN1) { // && tgtCoder == UTF16 + return -1; + } + // srcCoder == UTF16 && tgtCoder == LATIN1 + int min = tgtCount - 1; int i = min + fromIndex; + int strLastIndex = tgtCount - 1; + char strLastChar = (char)(tgt[strLastIndex] & 0xff); startSearchForLastChar: while (true) { - while (i >= min && source[i] != strLastChar) { + while (i >= min && StringUTF16.getChar(src, i) != strLastChar) { i--; } if (i < min) { return -1; } int j = i - 1; - int start = j - (targetCount - 1); + int start = j - strLastIndex; int k = strLastIndex - 1; - while (j > start) { - if (source[j--] != target[k--]) { + if (StringUTF16.getChar(src, j--) != (tgt[k--] & 0xff)) { i--; continue startSearchForLastChar; } } - return start - sourceOffset + 1; + return start + 1; } } @@ -1949,17 +1870,18 @@ public final class String * length of this {@code String} object. */ public String substring(int beginIndex) { - if (beginIndex <= 0) { - if (beginIndex < 0) { - throw new StringIndexOutOfBoundsException(beginIndex); - } - return this; + if (beginIndex < 0) { + throw new StringIndexOutOfBoundsException(beginIndex); } - int subLen = value.length - beginIndex; + int subLen = length() - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } - return new String(value, beginIndex, subLen); + if (beginIndex == 0) { + return this; + } + return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen) + : StringUTF16.newString(value, beginIndex, subLen); } /** @@ -1985,22 +1907,14 @@ public final class String * {@code endIndex}. */ public String substring(int beginIndex, int endIndex) { - if (beginIndex <= 0) { - if (beginIndex < 0) { - throw new StringIndexOutOfBoundsException(beginIndex); - } - if (endIndex == value.length) { - return this; - } - } - if (endIndex > value.length) { - throw new StringIndexOutOfBoundsException(endIndex); - } + int length = length(); + checkBoundsBeginEnd(beginIndex, endIndex, length); int subLen = endIndex - beginIndex; - if (subLen < 0) { - throw new StringIndexOutOfBoundsException(subLen); + if (beginIndex == 0 && endIndex == length) { + return this; } - return new String(value, beginIndex, subLen); + return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen) + : StringUTF16.newString(value, beginIndex, subLen); } /** @@ -2057,14 +1971,23 @@ public final class String * characters followed by the string argument's characters. */ public String concat(String str) { - int otherLen = str.length(); - if (otherLen == 0) { + int olen = str.length(); + if (olen == 0) { return this; } - int len = value.length; - char[] buf = Arrays.copyOf(value, len + otherLen); - str.getChars(buf, len); - return new String(buf, true); + if (coder() == str.coder()) { + byte[] val = this.value; + byte[] oval = str.value; + int len = val.length + oval.length; + byte[] buf = Arrays.copyOf(val, len); + System.arraycopy(oval, 0, buf, val.length, oval.length); + return new String(buf, coder); + } + int len = length(); + byte[] buf = StringUTF16.newBytesFor(len + olen); + getBytes(buf, 0, UTF16); + str.getBytes(buf, len, UTF16); + return new String(buf, UTF16); } /** @@ -2098,26 +2021,10 @@ public final class String */ public String replace(char oldChar, char newChar) { if (oldChar != newChar) { - char[] val = value; /* avoid getfield opcode */ - int len = val.length; - int i = -1; - - while (++i < len) { - if (val[i] == oldChar) { - break; - } - } - if (i < len) { - char[] buf = new char[len]; - for (int j = 0; j < i; j++) { - buf[j] = val[j]; - } - while (i < len) { - char c = val[i]; - buf[i] = (c == oldChar) ? newChar : c; - i++; - } - return new String(buf, true); + String ret = isLatin1() ? StringLatin1.replace(value, oldChar, newChar) + : StringUTF16.replace(value, oldChar, newChar); + if (ret != null) { + return ret; } } return this; @@ -2269,29 +2176,27 @@ public final class String * @since 1.5 */ public String replace(CharSequence target, CharSequence replacement) { - String starget = target.toString(); - String srepl = replacement.toString(); - int j = indexOf(starget); + String tgtStr = target.toString(); + String replStr = replacement.toString(); + int j = indexOf(tgtStr); if (j < 0) { return this; } - int targLen = starget.length(); - int targLen1 = Math.max(targLen, 1); - final char[] value = this.value; - final char[] replValue = srepl.value; - int newLenHint = value.length - targLen + replValue.length; + int tgtLen = tgtStr.length(); + int tgtLen1 = Math.max(tgtLen, 1); + int thisLen = length(); + + int newLenHint = thisLen - tgtLen + replStr.length(); if (newLenHint < 0) { throw new OutOfMemoryError(); } StringBuilder sb = new StringBuilder(newLenHint); int i = 0; do { - sb.append(value, i, j - i) - .append(replValue); - i = j + targLen; - } while (j < value.length && (j = indexOf(starget, j + targLen1)) > 0); - - return sb.append(value, i, value.length - i).toString(); + sb.append(this, i, j).append(replStr); + i = j + tgtLen; + } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0); + return sb.append(this, i, thisLen).toString(); } /** @@ -2388,7 +2293,7 @@ public final class String the second is not the ascii digit or ascii letter. */ char ch = 0; - if (((regex.value.length == 1 && + if (((regex.length() == 1 && ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || (regex.length() == 2 && regex.charAt(0) == '\\' && @@ -2408,8 +2313,9 @@ public final class String off = next + 1; } else { // last one //assert (list.size() == limit - 1); - list.add(substring(off, value.length)); - off = value.length; + int last = length(); + list.add(substring(off, last)); + off = last; break; } } @@ -2419,7 +2325,7 @@ public final class String // Add remaining segment if (!limited || list.size() < limit) - list.add(substring(off, value.length)); + list.add(substring(off, length())); // Construct result int resultSize = list.size(); @@ -2613,95 +2519,8 @@ public final class String * @since 1.1 */ public String toLowerCase(Locale locale) { - if (locale == null) { - throw new NullPointerException(); - } - int first; - boolean hasSurr = false; - final int len = value.length; - - // Now check if there are any characters that need to be changed, or are surrogate - for (first = 0 ; first < len; first++) { - int cp = (int)value[first]; - if (Character.isSurrogate((char)cp)) { - hasSurr = true; - break; - } - if (cp != Character.toLowerCase(cp)) { // no need to check Character.ERROR - break; - } - } - if (first == len) - return this; - char[] result = new char[len]; - System.arraycopy(value, 0, result, 0, first); // Just copy the first few - // lowerCase characters. - String lang = locale.getLanguage(); - if (lang == "tr" || lang == "az" || lang == "lt") { - return toLowerCaseEx(result, first, locale, true); - } - if (hasSurr) { - return toLowerCaseEx(result, first, locale, false); - } - for (int i = first; i < len; i++) { - int cp = (int)value[i]; - if (cp == '\u03A3' || // GREEK CAPITAL LETTER SIGMA - Character.isSurrogate((char)cp)) { - return toLowerCaseEx(result, i, locale, false); - } - if (cp == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE - return toLowerCaseEx(result, i, locale, true); - } - cp = Character.toLowerCase(cp); - if (!Character.isBmpCodePoint(cp)) { - return toLowerCaseEx(result, i, locale, false); - } - result[i] = (char)cp; - } - return new String(result, true); - } - - private String toLowerCaseEx(char[] result, int first, Locale locale, boolean localeDependent) { - int resultOffset = first; - int srcCount; - for (int i = first; i < value.length; i += srcCount) { - int srcChar = (int)value[i]; - int lowerChar; - char[] lowerCharArray; - srcCount = 1; - if (Character.isSurrogate((char)srcChar)) { - srcChar = codePointAt(i); - srcCount = Character.charCount(srcChar); - } - if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA - lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale); - } else { - lowerChar = Character.toLowerCase(srcChar); - } - if (Character.isBmpCodePoint(lowerChar)) { // Character.ERROR is not a bmp - result[resultOffset++] = (char)lowerChar; - } else { - if (lowerChar == Character.ERROR) { - lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale); - } else if (srcCount == 2) { - resultOffset += Character.toChars(lowerChar, result, resultOffset); - continue; - } else { - lowerCharArray = Character.toChars(lowerChar); - } - /* Grow result if needed */ - int mapLen = lowerCharArray.length; - if (mapLen > srcCount) { - char[] result2 = new char[result.length + mapLen - srcCount]; - System.arraycopy(result, 0, result2, 0, resultOffset); - result = result2; - } - for (int x = 0; x < mapLen; ++x) { - result[resultOffset++] = lowerCharArray[x]; - } - } - } - return new String(result, 0, resultOffset); + return isLatin1() ? StringLatin1.toLowerCase(this, value, locale) + : StringUTF16.toLowerCase(this, value, locale); } /** @@ -2776,98 +2595,8 @@ public final class String * @since 1.1 */ public String toUpperCase(Locale locale) { - if (locale == null) { - throw new NullPointerException(); - } - int first; - boolean hasSurr = false; - final int len = value.length; - - // Now check if there are any characters that need to be changed, or are surrogate - for (first = 0 ; first < len; first++ ) { - int cp = (int)value[first]; - if (Character.isSurrogate((char)cp)) { - hasSurr = true; - break; - } - if (cp != Character.toUpperCaseEx(cp)) { // no need to check Character.ERROR - break; - } - } - if (first == len) { - return this; - } - char[] result = new char[len]; - System.arraycopy(value, 0, result, 0, first); // Just copy the first few - // upperCase characters. - String lang = locale.getLanguage(); - if (lang == "tr" || lang == "az" || lang == "lt") { - return toUpperCaseEx(result, first, locale, true); - } - if (hasSurr) { - return toUpperCaseEx(result, first, locale, false); - } - for (int i = first; i < len; i++) { - int cp = (int)value[i]; - if (Character.isSurrogate((char)cp)) { - return toUpperCaseEx(result, i, locale, false); - } - cp = Character.toUpperCaseEx(cp); - if (!Character.isBmpCodePoint(cp)) { // Character.ERROR is not bmp - return toUpperCaseEx(result, i, locale, false); - } - result[i] = (char)cp; - } - return new String(result, true); - } - - private String toUpperCaseEx(char[] result, int first, Locale locale, - boolean localeDependent) { - int resultOffset = first; - int srcCount; - for (int i = first; i < value.length; i += srcCount) { - int srcChar = (int)value[i]; - int upperChar; - char[] upperCharArray; - srcCount = 1; - if (Character.isSurrogate((char)srcChar)) { - srcChar = codePointAt(i); - srcCount = Character.charCount(srcChar); - } - if (localeDependent) { - upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale); - } else { - upperChar = Character.toUpperCaseEx(srcChar); - } - if (Character.isBmpCodePoint(upperChar)) { - result[resultOffset++] = (char)upperChar; - } else { - if (upperChar == Character.ERROR) { - if (localeDependent) { - upperCharArray = - ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale); - } else { - upperCharArray = Character.toUpperCaseCharArray(srcChar); - } - } else if (srcCount == 2) { - resultOffset += Character.toChars(upperChar, result, resultOffset); - continue; - } else { - upperCharArray = Character.toChars(upperChar); - } - /* Grow result if needed */ - int mapLen = upperCharArray.length; - if (mapLen > srcCount) { - char[] result2 = new char[result.length + mapLen - srcCount]; - System.arraycopy(result, 0, result2, 0, resultOffset); - result = result2; - } - for (int x = 0; x < mapLen; ++x) { - result[resultOffset++] = upperCharArray[x]; - } - } - } - return new String(result, 0, resultOffset); + return isLatin1() ? StringLatin1.toUpperCase(this, value, locale) + : StringUTF16.toUpperCase(this, value, locale); } /** @@ -2925,17 +2654,9 @@ public final class String * trailing white space. */ public String trim() { - char[] val = value; /* avoid getfield opcode */ - int end = val.length; - int beg = 0; - - while ((beg < end) && (val[beg] <= ' ')) { - beg++; - } - while ((beg < end) && (val[end - 1] <= ' ')) { - end--; - } - return substring(beg, end); + String ret = isLatin1() ? StringLatin1.trim(value) + : StringUTF16.trim(value); + return ret == null ? this : ret; } /** @@ -2947,63 +2668,6 @@ public final class String return this; } - static class IntCharArraySpliterator implements Spliterator.OfInt { - private final char[] array; - private int index; // current index, modified on advance/split - private final int fence; // one past last index - private final int cs; - - IntCharArraySpliterator(char[] array, int acs) { - this(array, 0, array.length, acs); - } - - IntCharArraySpliterator(char[] array, int origin, int fence, int acs) { - this.array = array; - this.index = origin; - this.fence = fence; - this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED - | Spliterator.SUBSIZED; - } - - @Override - public OfInt trySplit() { - int lo = index, mid = (lo + fence) >>> 1; - return (lo >= mid) - ? null - : new IntCharArraySpliterator(array, lo, index = mid, cs); - } - - @Override - public void forEachRemaining(IntConsumer action) { - char[] a; int i, hi; // hoist accesses and checks from loop - if (action == null) - throw new NullPointerException(); - if ((a = array).length >= (hi = fence) && - (i = index) >= 0 && i < (index = hi)) { - do { action.accept(a[i]); } while (++i < hi); - } - } - - @Override - public boolean tryAdvance(IntConsumer action) { - if (action == null) - throw new NullPointerException(); - if (index >= 0 && index < fence) { - action.accept(array[index++]); - return true; - } - return false; - } - - @Override - public long estimateSize() { return (long)(fence - index); } - - @Override - public int characteristics() { - return cs; - } - } - /** * Returns a stream of {@code int} zero-extending the {@code char} values * from this sequence. Any char which maps to a <a @@ -3016,93 +2680,11 @@ public final class String @Override public IntStream chars() { return StreamSupport.intStream( - new IntCharArraySpliterator(value, Spliterator.IMMUTABLE), false); + isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE) + : new StringUTF16.CharsSpliterator(value, Spliterator.IMMUTABLE), + false); } - static class CodePointsSpliterator implements Spliterator.OfInt { - private final char[] array; - private int index; // current index, modified on advance/split - private final int fence; // one past last index - private final int cs; - - CodePointsSpliterator(char[] array, int acs) { - this(array, 0, array.length, acs); - } - - CodePointsSpliterator(char[] array, int origin, int fence, int acs) { - this.array = array; - this.index = origin; - this.fence = fence; - this.cs = acs | Spliterator.ORDERED; - } - - @Override - public OfInt trySplit() { - int lo = index, mid = (lo + fence) >>> 1; - if (lo >= mid) - return null; - - int midOneLess; - // If the mid-point intersects a surrogate pair - if (Character.isLowSurrogate(array[mid]) && - Character.isHighSurrogate(array[midOneLess = (mid -1)])) { - // If there is only one pair it cannot be split - if (lo >= midOneLess) - return null; - // Shift the mid-point to align with the surrogate pair - return new CodePointsSpliterator(array, lo, index = midOneLess, cs); - } - return new CodePointsSpliterator(array, lo, index = mid, cs); - } - - @Override - public void forEachRemaining(IntConsumer action) { - char[] a; int i, hi; // hoist accesses and checks from loop - if (action == null) - throw new NullPointerException(); - if ((a = array).length >= (hi = fence) && - (i = index) >= 0 && i < (index = hi)) { - do { - i = advance(a, i, hi, action); - } while (i < hi); - } - } - - @Override - public boolean tryAdvance(IntConsumer action) { - if (action == null) - throw new NullPointerException(); - if (index >= 0 && index < fence) { - index = advance(array, index, fence, action); - return true; - } - return false; - } - - // Advance one code point from the index, i, and return the next - // index to advance from - private static int advance(char[] a, int i, int hi, IntConsumer action) { - char c1 = a[i++]; - int cp = c1; - if (Character.isHighSurrogate(c1) && i < hi) { - char c2 = a[i]; - if (Character.isLowSurrogate(c2)) { - i++; - cp = Character.toCodePoint(c1, c2); - } - } - action.accept(cp); - return i; - } - - @Override - public long estimateSize() { return (long)(fence - index); } - - @Override - public int characteristics() { - return cs; - } - } /** * Returns a stream of code point values from this sequence. Any surrogate @@ -3118,7 +2700,9 @@ public final class String @Override public IntStream codePoints() { return StreamSupport.intStream( - new CodePointsSpliterator(value, Spliterator.IMMUTABLE), false); + isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE) + : new StringUTF16.CodePointsSpliterator(value, Spliterator.IMMUTABLE), + false); } /** @@ -3129,10 +2713,8 @@ public final class String * the character sequence represented by this string. */ public char[] toCharArray() { - // Cannot use Arrays.copyOf because of class initialization order issues - char[] result = new char[value.length]; - System.arraycopy(value, 0, result, 0, value.length); - return result; + return isLatin1() ? StringLatin1.toChars(value) + : StringUTF16.toChars(value); } /** @@ -3315,7 +2897,10 @@ public final class String * as its single character the argument {@code c}. */ public static String valueOf(char c) { - return new String(new char[]{c}, true); + if (COMPACT_STRINGS && StringLatin1.canEncode(c)) { + return new String(StringLatin1.toBytes(c), LATIN1); + } + return new String(StringUTF16.toBytes(c), UTF16); } /** @@ -3398,4 +2983,145 @@ public final class String * guaranteed to be from a pool of unique strings. */ public native String intern(); + + //////////////////////////////////////////////////////////////// + + /** + * Copy character bytes from this string into dst starting at dstBegin. + * This method doesn't perform any range checking. + * + * Invoker guarantees: dst is in UTF16 (inflate itself for asb), if two + * coders are different, and dst is big enough (range check) + * + * @param dstBegin the char index, not offset of byte[] + * @param coder the coder of dst[] + */ + void getBytes(byte dst[], int dstBegin, byte coder) { + if (coder() == coder) { + System.arraycopy(value, 0, dst, dstBegin << coder, value.length); + } else { // this.coder == LATIN && coder == UTF16 + StringLatin1.inflate(value, 0, dst, dstBegin, value.length); + } + } + + /* + * Package private constructor. Trailing Void argument is there for + * disambiguating it against other (public) constructors. + * + * Stores the char[] value into a byte[] that each byte represents + * the8 low-order bits of the corresponding character, if the char[] + * contains only latin1 character. Or a byte[] that stores all + * characters in their byte sequences defined by the {@code StringUTF16}. + */ + String(char[] value, int off, int len, Void sig) { + if (len == 0) { + this.value = "".value; + this.coder = "".coder; + return; + } + if (COMPACT_STRINGS) { + byte[] val = StringUTF16.compress(value, off, len); + if (val != null) { + this.value = val; + this.coder = LATIN1; + return; + } + } + this.coder = UTF16; + this.value = StringUTF16.toBytes(value, off, len); + } + + /* + * Package private constructor. Trailing Void argument is there for + * disambiguating it against other (public) constructors. + */ + String(AbstractStringBuilder asb, Void sig) { + byte[] val = asb.getValue(); + int length = asb.length(); + if (asb.isLatin1()) { + this.coder = LATIN1; + this.value = Arrays.copyOfRange(val, 0, length); + } else { + if (COMPACT_STRINGS) { + byte[] buf = StringUTF16.compress(val, 0, length); + if (buf != null) { + this.coder = LATIN1; + this.value = buf; + return; + } + } + this.coder = UTF16; + this.value = Arrays.copyOfRange(val, 0, length << 1); + } + } + + /* + * Package private constructor which shares value array for speed. + */ + String(byte[] value, byte coder) { + this.value = value; + this.coder = coder; + } + + byte coder() { + return COMPACT_STRINGS ? coder : UTF16; + } + + private boolean isLatin1() { + return COMPACT_STRINGS && coder == LATIN1; + } + + static final byte LATIN1 = 0; + static final byte UTF16 = 1; + + /* + * StringIndexOutOfBoundsException if {@code index} is + * negative or greater than or equal to {@code length}. + */ + static void checkIndex(int index, int length) { + if (index < 0 || index >= length) { + throw new StringIndexOutOfBoundsException("index " + index); + } + } + + /* + * StringIndexOutOfBoundsException if {@code offset} + * is negative or greater than {@code length}. + */ + static void checkOffset(int offset, int length) { + if (offset < 0 || offset > length) { + throw new StringIndexOutOfBoundsException("offset " + offset + + ",length " + length); + } + } + + /* + * Check {@code offset}, {@code count} against {@code 0} and {@code length} + * bounds. + * + * @throws StringIndexOutOfBoundsException + * If {@code offset} is negative, {@code count} is negative, + * or {@code offset} is greater than {@code length - count} + */ + private static void checkBoundsOffCount(int offset, int count, int length) { + if (offset < 0 || count < 0 || offset > length - count) { + throw new StringIndexOutOfBoundsException( + "offset " + offset + ", count " + count + ", length " + length); + } + } + + /* + * Check {@code begin}, {@code end} against {@code 0} and {@code length} + * bounds. + * + * @throws StringIndexOutOfBoundsException + * If {@code begin} is negative, {@code begin} is greater than + * {@code end}, or {@code end} is greater than {@code length}. + */ + private static void checkBoundsBeginEnd(int begin, int end, int length) { + if (begin < 0 || begin > end || end > length) { + throw new StringIndexOutOfBoundsException( + "begin " + begin + ", end " + end + ", length " + length); + } + } } diff --git a/jdk/src/java.base/share/classes/java/lang/StringBuffer.java b/jdk/src/java.base/share/classes/java/lang/StringBuffer.java index a20645463fa69b5cf72264c3351a0ec31e81359b..65bbe14e34e50d2b61910a3733e71135b126bd39 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringBuffer.java +++ b/jdk/src/java.base/share/classes/java/lang/StringBuffer.java @@ -104,7 +104,7 @@ import jdk.internal.HotSpotIntrinsicCandidate; * A cache of the last value returned by toString. Cleared * whenever the StringBuffer is modified. */ - private transient char[] toStringCache; + private transient String toStringCache; /** use serialVersionUID from JDK 1.0.2 for interoperability */ static final long serialVersionUID = 3388685877147921107L; @@ -169,15 +169,13 @@ import jdk.internal.HotSpotIntrinsicCandidate; @Override public synchronized int capacity() { - return value.length; + return super.capacity(); } @Override public synchronized void ensureCapacity(int minimumCapacity) { - if (minimumCapacity > value.length) { - expandCapacity(minimumCapacity); - } + super.ensureCapacity(minimumCapacity); } /** @@ -204,9 +202,7 @@ import jdk.internal.HotSpotIntrinsicCandidate; */ @Override public synchronized char charAt(int index) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); - return value[index]; + return super.charAt(index); } /** @@ -261,10 +257,8 @@ import jdk.internal.HotSpotIntrinsicCandidate; */ @Override public synchronized void setCharAt(int index, char ch) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); toStringCache = null; - value[index] = ch; + super.setCharAt(index, ch); } @Override @@ -680,9 +674,11 @@ import jdk.internal.HotSpotIntrinsicCandidate; @HotSpotIntrinsicCandidate public synchronized String toString() { if (toStringCache == null) { - toStringCache = Arrays.copyOfRange(value, 0, count); + return toStringCache = + isLatin1() ? StringLatin1.newString(value, 0, count) + : StringUTF16.newString(value, 0, count); } - return new String(toStringCache, true); + return new String(toStringCache); } /** @@ -710,7 +706,13 @@ import jdk.internal.HotSpotIntrinsicCandidate; private synchronized void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { java.io.ObjectOutputStream.PutField fields = s.putFields(); - fields.put("value", value); + char[] val = new char[capacity()]; + if (isLatin1()) { + StringLatin1.getChars(value, 0, count, val, 0); + } else { + StringUTF16.getChars(value, 0, count, val, 0); + } + fields.put("value", val); fields.put("count", count); fields.put("shared", false); s.writeFields(); @@ -723,7 +725,12 @@ import jdk.internal.HotSpotIntrinsicCandidate; private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { java.io.ObjectInputStream.GetField fields = s.readFields(); - value = (char[])fields.get("value", null); + char[] val = (char[])fields.get("value", null); + initBytes(val, 0, val.length); count = fields.get("count", 0); } + + protected synchronized void getBytes(byte dst[], int dstBegin, byte coder) { + super.getBytes(dst, dstBegin, coder); + } } diff --git a/jdk/src/java.base/share/classes/java/lang/StringBuilder.java b/jdk/src/java.base/share/classes/java/lang/StringBuilder.java index 9d4ccf3dbbee9330e4b31da22983557047648eec..7d1e46a423f9debb5c9e357f1aaea2cf4eba9321 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/StringBuilder.java @@ -412,7 +412,8 @@ public final class StringBuilder @HotSpotIntrinsicCandidate public String toString() { // Create a copy, don't share the array - return new String(value, 0, count); + return isLatin1() ? StringLatin1.newString(value, 0, count) + : StringUTF16.newStringSB(value, 0, count); } /** @@ -430,7 +431,13 @@ public final class StringBuilder throws java.io.IOException { s.defaultWriteObject(); s.writeInt(count); - s.writeObject(value); + char[] val = new char[capacity()]; + if (isLatin1()) { + StringLatin1.getChars(value, 0, count, val, 0); + } else { + StringUTF16.getChars(value, 0, count, val, 0); + } + s.writeObject(val); } /** @@ -441,7 +448,8 @@ public final class StringBuilder throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); count = s.readInt(); - value = (char[]) s.readObject(); + char[] val = (char[]) s.readObject(); + initBytes(val, 0, val.length); } } diff --git a/jdk/src/java.base/share/classes/java/lang/StringCoding.java b/jdk/src/java.base/share/classes/java/lang/StringCoding.java index d770156da2c9bf3f46b5ed46078063d058dfff21..b1e25d5128f6fb83871cc4bcb6856f3d310b0d2d 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringCoding.java +++ b/jdk/src/java.base/share/classes/java/lang/StringCoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, 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 @@ -38,11 +38,19 @@ import java.nio.charset.CodingErrorAction; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; import java.util.Arrays; +import jdk.internal.HotSpotIntrinsicCandidate; import sun.misc.MessageUtils; import sun.nio.cs.HistoricallyNamedCharset; import sun.nio.cs.ArrayDecoder; import sun.nio.cs.ArrayEncoder; +import static java.lang.String.LATIN1; +import static java.lang.String.UTF16; +import static java.lang.String.COMPACT_STRINGS; +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * Utility class for string encoding and decoding. */ @@ -72,23 +80,13 @@ class StringCoding { // Trim the given byte array to the given length // - private static byte[] safeTrim(byte[] ba, int len, Charset cs, boolean isTrusted) { + private static byte[] safeTrim(byte[] ba, int len, boolean isTrusted) { if (len == ba.length && (isTrusted || System.getSecurityManager() == null)) return ba; else return Arrays.copyOf(ba, len); } - // Trim the given char array to the given length - // - private static char[] safeTrim(char[] ca, int len, - Charset cs, boolean isTrusted) { - if (len == ca.length && (isTrusted || System.getSecurityManager() == null)) - return ca; - else - return Arrays.copyOf(ca, len); - } - private static int scale(int len, float expansionFactor) { // We need to perform double, not float, arithmetic; otherwise // we lose low order bits when len is larger than 2**24. @@ -117,21 +115,64 @@ class StringCoding { } } + static class Result { + byte[] value; + byte coder; + + Result with() { + coder = COMPACT_STRINGS ? LATIN1 : UTF16; + value = new byte[0]; + return this; + } + + Result with(char[] val, int off, int len) { + if (String.COMPACT_STRINGS) { + byte[] bs = StringUTF16.compress(val, off, len); + if (bs != null) { + value = bs; + coder = LATIN1; + return this; + } + } + coder = UTF16; + value = StringUTF16.toBytes(val, off, len); + return this; + } + + Result with(byte[] val, byte coder) { + this.coder = coder; + value = val; + return this; + } + } + + @HotSpotIntrinsicCandidate + private static boolean hasNegatives(byte[] ba, int off, int len) { + for (int i = off; i < off + len; i++) { + if (ba[i] < 0) { + return true; + } + } + return false; + } // -- Decoding -- - private static class StringDecoder { + static class StringDecoder { private final String requestedCharsetName; private final Charset cs; + private final boolean isASCIICompatible; private final CharsetDecoder cd; - private final boolean isTrusted; + protected final Result result; - private StringDecoder(Charset cs, String rcn) { + StringDecoder(Charset cs, String rcn) { this.requestedCharsetName = rcn; this.cs = cs; this.cd = cs.newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); - this.isTrusted = (cs.getClass().getClassLoader0() == null); + this.result = new Result(); + this.isASCIICompatible = (cd instanceof ArrayDecoder) && + ((ArrayDecoder)cd).isASCIICompatible(); } String charsetName() { @@ -144,36 +185,58 @@ class StringCoding { return requestedCharsetName; } - char[] decode(byte[] ba, int off, int len) { + Result decode(byte[] ba, int off, int len) { + if (len == 0) { + return result.with(); + } + // fastpath for ascii compatible + if (isASCIICompatible && !hasNegatives(ba, off, len)) { + if (COMPACT_STRINGS) { + return result.with(Arrays.copyOfRange(ba, off, off + len), + LATIN1); + } else { + return result.with(StringLatin1.inflate(ba, off, len), UTF16); + } + } int en = scale(len, cd.maxCharsPerByte()); char[] ca = new char[en]; - if (len == 0) - return ca; if (cd instanceof ArrayDecoder) { int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca); - return safeTrim(ca, clen, cs, isTrusted); + return result.with(ca, 0, clen); + } + cd.reset(); + ByteBuffer bb = ByteBuffer.wrap(ba, off, len); + CharBuffer cb = CharBuffer.wrap(ca); + try { + CoderResult cr = cd.decode(bb, cb, true); + if (!cr.isUnderflow()) + cr.throwException(); + cr = cd.flush(cb); + if (!cr.isUnderflow()) + cr.throwException(); + } catch (CharacterCodingException x) { + // Substitution is always enabled, + // so this shouldn't happen + throw new Error(x); + } + return result.with(ca, 0, cb.position()); + } + } + + private static class StringDecoder8859_1 extends StringDecoder { + StringDecoder8859_1(Charset cs, String rcn) { + super(cs, rcn); + } + Result decode(byte[] ba, int off, int len) { + if (COMPACT_STRINGS) { + return result.with(Arrays.copyOfRange(ba, off, off + len), LATIN1); } else { - cd.reset(); - ByteBuffer bb = ByteBuffer.wrap(ba, off, len); - CharBuffer cb = CharBuffer.wrap(ca); - try { - CoderResult cr = cd.decode(bb, cb, true); - if (!cr.isUnderflow()) - cr.throwException(); - cr = cd.flush(cb); - if (!cr.isUnderflow()) - cr.throwException(); - } catch (CharacterCodingException x) { - // Substitution is always enabled, - // so this shouldn't happen - throw new Error(x); - } - return safeTrim(ca, cb.position(), cs, isTrusted); + return result.with(StringLatin1.inflate(ba, off, len), UTF16); } } } - static char[] decode(String charsetName, byte[] ba, int off, int len) + static Result decode(String charsetName, byte[] ba, int off, int len) throws UnsupportedEncodingException { StringDecoder sd = deref(decoder); @@ -183,8 +246,15 @@ class StringCoding { sd = null; try { Charset cs = lookupCharset(csn); - if (cs != null) - sd = new StringDecoder(cs, csn); + if (cs != null) { + if (cs == UTF_8) { + sd = new StringDecoderUTF8(cs, csn); + } else if (cs == ISO_8859_1) { + sd = new StringDecoder8859_1(cs, csn); + } else { + sd = new StringDecoder(cs, csn); + } + } } catch (IllegalCharsetNameException x) {} if (sd == null) throw new UnsupportedEncodingException(csn); @@ -193,7 +263,7 @@ class StringCoding { return sd.decode(ba, off, len); } - static char[] decode(Charset cs, byte[] ba, int off, int len) { + static Result decode(Charset cs, byte[] ba, int off, int len) { // (1)We never cache the "external" cs, the only benefit of creating // an additional StringDe/Encoder object to wrap it is to share the // de/encode() method. These SD/E objects are short-lived, the young-gen @@ -210,44 +280,57 @@ class StringCoding { // check (... && (isTrusted || SM == null || getClassLoader0())) in trim // but it then can be argued that the SM is null when the operation // is started... + if (cs == UTF_8) { + return StringDecoderUTF8.decode(ba, off, len, new Result()); + } CharsetDecoder cd = cs.newDecoder(); + // ascii fastpath + if (cs == ISO_8859_1 || ((cd instanceof ArrayDecoder) && + ((ArrayDecoder)cd).isASCIICompatible() && + !hasNegatives(ba, off, len))) { + if (COMPACT_STRINGS) { + return new Result().with(Arrays.copyOfRange(ba, off, off + len), + LATIN1); + } else { + return new Result().with(StringLatin1.inflate(ba, off, len), UTF16); + } + } int en = scale(len, cd.maxCharsPerByte()); - char[] ca = new char[en]; - if (len == 0) - return ca; - boolean isTrusted = false; - if (System.getSecurityManager() != null) { - if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) { - ba = Arrays.copyOfRange(ba, off, off + len); - off = 0; - } + if (len == 0) { + return new Result().with(); + } + if (System.getSecurityManager() != null && + cs.getClass().getClassLoader0() != null) { + ba = Arrays.copyOfRange(ba, off, off + len); + off = 0; } cd.onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .reset(); + + char[] ca = new char[en]; if (cd instanceof ArrayDecoder) { int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca); - return safeTrim(ca, clen, cs, isTrusted); - } else { - ByteBuffer bb = ByteBuffer.wrap(ba, off, len); - CharBuffer cb = CharBuffer.wrap(ca); - try { - CoderResult cr = cd.decode(bb, cb, true); - if (!cr.isUnderflow()) - cr.throwException(); - cr = cd.flush(cb); - if (!cr.isUnderflow()) - cr.throwException(); - } catch (CharacterCodingException x) { - // Substitution is always enabled, - // so this shouldn't happen - throw new Error(x); - } - return safeTrim(ca, cb.position(), cs, isTrusted); + return new Result().with(ca, 0, clen); } + ByteBuffer bb = ByteBuffer.wrap(ba, off, len); + CharBuffer cb = CharBuffer.wrap(ca); + try { + CoderResult cr = cd.decode(bb, cb, true); + if (!cr.isUnderflow()) + cr.throwException(); + cr = cd.flush(cb); + if (!cr.isUnderflow()) + cr.throwException(); + } catch (CharacterCodingException x) { + // Substitution is always enabled, + // so this shouldn't happen + throw new Error(x); + } + return new Result().with(ca, 0, cb.position()); } - static char[] decode(byte[] ba, int off, int len) { + static Result decode(byte[] ba, int off, int len) { String csn = Charset.defaultCharset().name(); try { // use charset name decode() variant which provides caching. @@ -273,6 +356,7 @@ class StringCoding { private static class StringEncoder { private Charset cs; private CharsetEncoder ce; + private final boolean isASCIICompatible; private final String requestedCharsetName; private final boolean isTrusted; @@ -283,6 +367,8 @@ class StringCoding { .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); this.isTrusted = (cs.getClass().getClassLoader0() == null); + this.isASCIICompatible = (ce instanceof ArrayEncoder) && + ((ArrayEncoder)ce).isASCIICompatible(); } String charsetName() { @@ -295,36 +381,186 @@ class StringCoding { return requestedCharsetName; } - byte[] encode(char[] ca, int off, int len) { + byte[] encode(byte coder, byte[] val) { + // fastpath for ascii compatible + if (coder == LATIN1 && isASCIICompatible && + !hasNegatives(val, 0, val.length)) { + return Arrays.copyOf(val, val.length); + } + int len = val.length >> coder; // assume LATIN1=0/UTF16=1; int en = scale(len, ce.maxBytesPerChar()); byte[] ba = new byte[en]; - if (len == 0) + if (len == 0) { return ba; + } if (ce instanceof ArrayEncoder) { - int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba); - return safeTrim(ba, blen, cs, isTrusted); - } else { - ce.reset(); - ByteBuffer bb = ByteBuffer.wrap(ba); - CharBuffer cb = CharBuffer.wrap(ca, off, len); - try { - CoderResult cr = ce.encode(cb, bb, true); - if (!cr.isUnderflow()) - cr.throwException(); - cr = ce.flush(bb); - if (!cr.isUnderflow()) - cr.throwException(); - } catch (CharacterCodingException x) { - // Substitution is always enabled, - // so this shouldn't happen - throw new Error(x); + if (!isTrusted) { + val = Arrays.copyOf(val, val.length); + } + int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba) + : ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba); + if (blen != -1) { + return safeTrim(ba, blen, isTrusted); + } + } + char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val) + : StringUTF16.toChars(val); + ce.reset(); + ByteBuffer bb = ByteBuffer.wrap(ba); + CharBuffer cb = CharBuffer.wrap(ca, 0, len); + try { + CoderResult cr = ce.encode(cb, bb, true); + if (!cr.isUnderflow()) + cr.throwException(); + cr = ce.flush(bb); + if (!cr.isUnderflow()) + cr.throwException(); + } catch (CharacterCodingException x) { + // Substitution is always enabled, + // so this shouldn't happen + throw new Error(x); + } + return safeTrim(ba, bb.position(), isTrusted); + } + } + + @HotSpotIntrinsicCandidate + private static int implEncodeISOArray(byte[] sa, int sp, + byte[] da, int dp, int len) { + int i = 0; + for (; i < len; i++) { + char c = StringUTF16.getChar(sa, sp++); + if (c > '\u00FF') + break; + da[dp++] = (byte)c; + } + return i; + } + + static byte[] encode8859_1(byte coder, byte[] val) { + if (coder == LATIN1) { + return Arrays.copyOf(val, val.length); + } + int len = val.length >> 1; + byte[] dst = new byte[len]; + int dp = 0; + int sp = 0; + int sl = len; + while (sp < sl) { + int ret = implEncodeISOArray(val, sp, dst, dp, len); + sp = sp + ret; + dp = dp + ret; + if (ret != len) { + char c = StringUTF16.getChar(val, sp++); + if (Character.isHighSurrogate(c) && sp < sl && + Character.isLowSurrogate(StringUTF16.getChar(val, sp))) { + sp++; + } + dst[dp++] = '?'; + len = sl - sp; + } + } + if (dp == dst.length) { + return dst; + } + return Arrays.copyOf(dst, dp); + } + + static byte[] encodeASCII(byte coder, byte[] val) { + if (coder == LATIN1) { + byte[] dst = new byte[val.length]; + for (int i = 0; i < val.length; i++) { + if (val[i] < 0) { + dst[i] = '?'; + } else { + dst[i] = val[i]; } - return safeTrim(ba, bb.position(), cs, isTrusted); } + return dst; } + int len = val.length >> 1; + byte[] dst = new byte[len]; + int dp = 0; + for (int i = 0; i < len; i++) { + char c = StringUTF16.getChar(val, i); + if (c < 0x80) { + dst[dp++] = (byte)c; + continue; + } + if (Character.isHighSurrogate(c) && i + 1 < len && + Character.isLowSurrogate(StringUTF16.getChar(val, i + 1))) { + i++; + } + dst[dp++] = '?'; + } + if (len == dp) { + return dst; + } + return Arrays.copyOf(dst, dp); } - static byte[] encode(String charsetName, char[] ca, int off, int len) + static byte[] encodeUTF8(byte coder, byte[] val) { + int dp = 0; + byte[] dst; + if (coder == LATIN1) { + dst = new byte[val.length << 1]; + for (int sp = 0; sp < val.length; sp++) { + byte c = val[sp]; + if (c < 0) { + dst[dp++] = (byte)(0xc0 | ((c & 0xff) >> 6)); + dst[dp++] = (byte)(0x80 | (c & 0x3f)); + } else { + dst[dp++] = c; + } + } + } else { + int sp = 0; + int sl = val.length >> 1; + dst = new byte[sl * 3]; + char c; + while (sp < sl && (c = StringUTF16.getChar(val, sp)) < '\u0080') { + // ascii fast loop; + dst[dp++] = (byte)c; + sp++; + } + while (sp < sl) { + c = StringUTF16.getChar(val, sp++); + if (c < 0x80) { + dst[dp++] = (byte)c; + } else if (c < 0x800) { + dst[dp++] = (byte)(0xc0 | (c >> 6)); + dst[dp++] = (byte)(0x80 | (c & 0x3f)); + } else if (Character.isSurrogate(c)) { + int uc = -1; + char c2; + if (Character.isHighSurrogate(c) && sp < sl && + Character.isLowSurrogate(c2 = StringUTF16.getChar(val, sp))) { + uc = Character.toCodePoint(c, c2); + } + if (uc < 0) { + dst[dp++] = '?'; + } else { + dst[dp++] = (byte)(0xf0 | ((uc >> 18))); + dst[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f)); + dst[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f)); + dst[dp++] = (byte)(0x80 | (uc & 0x3f)); + sp++; // 2 chars + } + } else { + // 3 bytes, 16 bits + dst[dp++] = (byte)(0xe0 | ((c >> 12))); + dst[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f)); + dst[dp++] = (byte)(0x80 | (c & 0x3f)); + } + } + } + if (dp == dst.length) { + return dst; + } + return Arrays.copyOf(dst, dp); + } + + static byte[] encode(String charsetName, byte coder, byte[] val) throws UnsupportedEncodingException { StringEncoder se = deref(encoder); @@ -334,62 +570,88 @@ class StringCoding { se = null; try { Charset cs = lookupCharset(csn); - if (cs != null) + if (cs != null) { + if (cs == UTF_8) { + return encodeUTF8(coder, val); + } else if (cs == ISO_8859_1) { + return encode8859_1(coder, val); + } else if (cs == US_ASCII) { + return encodeASCII(coder, val); + } se = new StringEncoder(cs, csn); + } } catch (IllegalCharsetNameException x) {} - if (se == null) + if (se == null) { throw new UnsupportedEncodingException (csn); + } set(encoder, se); } - return se.encode(ca, off, len); + return se.encode(coder, val); } - static byte[] encode(Charset cs, char[] ca, int off, int len) { + static byte[] encode(Charset cs, byte coder, byte[] val) { + if (cs == UTF_8) { + return encodeUTF8(coder, val); + } else if (cs == ISO_8859_1) { + return encode8859_1(coder, val); + } else if (cs == US_ASCII) { + return encodeASCII(coder, val); + } CharsetEncoder ce = cs.newEncoder(); + // fastpath for ascii compatible + if (coder == LATIN1 && (((ce instanceof ArrayEncoder) && + ((ArrayEncoder)ce).isASCIICompatible() && + !hasNegatives(val, 0, val.length)))) { + return Arrays.copyOf(val, val.length); + } + int len = val.length >> coder; // assume LATIN1=0/UTF16=1; int en = scale(len, ce.maxBytesPerChar()); byte[] ba = new byte[en]; - if (len == 0) + if (len == 0) { return ba; - boolean isTrusted = false; - if (System.getSecurityManager() != null) { - if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) { - ca = Arrays.copyOfRange(ca, off, off + len); - off = 0; - } } + boolean isTrusted = System.getSecurityManager() == null || + cs.getClass().getClassLoader0() == null; ce.onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .reset(); if (ce instanceof ArrayEncoder) { - int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba); - return safeTrim(ba, blen, cs, isTrusted); - } else { - ByteBuffer bb = ByteBuffer.wrap(ba); - CharBuffer cb = CharBuffer.wrap(ca, off, len); - try { - CoderResult cr = ce.encode(cb, bb, true); - if (!cr.isUnderflow()) - cr.throwException(); - cr = ce.flush(bb); - if (!cr.isUnderflow()) - cr.throwException(); - } catch (CharacterCodingException x) { - throw new Error(x); + if (!isTrusted) { + val = Arrays.copyOf(val, val.length); + } + int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba) + : ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba); + if (blen != -1) { + return safeTrim(ba, blen, isTrusted); } - return safeTrim(ba, bb.position(), cs, isTrusted); } + char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val) + : StringUTF16.toChars(val); + ByteBuffer bb = ByteBuffer.wrap(ba); + CharBuffer cb = CharBuffer.wrap(ca, 0, len); + try { + CoderResult cr = ce.encode(cb, bb, true); + if (!cr.isUnderflow()) + cr.throwException(); + cr = ce.flush(bb); + if (!cr.isUnderflow()) + cr.throwException(); + } catch (CharacterCodingException x) { + throw new Error(x); + } + return safeTrim(ba, bb.position(), isTrusted); } - static byte[] encode(char[] ca, int off, int len) { + static byte[] encode(byte coder, byte[] val) { String csn = Charset.defaultCharset().name(); try { // use charset name encode() variant which provides caching. - return encode(csn, ca, off, len); + return encode(csn, coder, val); } catch (UnsupportedEncodingException x) { warnUnsupportedCharset(csn); } try { - return encode("ISO-8859-1", ca, off, len); + return encode("ISO-8859-1", coder, val); } catch (UnsupportedEncodingException x) { // If this code is hit during VM initialization, MessageUtils is // the only way we will be able to get any kind of error message. diff --git a/jdk/src/java.base/share/classes/java/lang/StringDecoderUTF8.java b/jdk/src/java.base/share/classes/java/lang/StringDecoderUTF8.java new file mode 100644 index 0000000000000000000000000000000000000000..1b504df2574025b08c2e7b5cbd716a76b1517f51 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/StringDecoderUTF8.java @@ -0,0 +1,235 @@ +/* + * 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.nio.charset.Charset; +import java.util.Arrays; + +import static java.lang.String.LATIN1; +import static java.lang.String.UTF16; +import static java.lang.String.COMPACT_STRINGS; +import static java.lang.Character.isSurrogate; +import static java.lang.Character.highSurrogate; +import static java.lang.Character.lowSurrogate; +import static java.lang.Character.isSupplementaryCodePoint; +import static java.lang.StringUTF16.putChar; + +class StringDecoderUTF8 extends StringCoding.StringDecoder { + + StringDecoderUTF8(Charset cs, String rcn) { + super(cs, rcn); + } + + private static boolean isNotContinuation(int b) { + return (b & 0xc0) != 0x80; + } + + private static boolean isMalformed3(int b1, int b2, int b3) { + return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) || + (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80; + } + + private static boolean isMalformed3_2(int b1, int b2) { + return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) || + (b2 & 0xc0) != 0x80; + } + + private static boolean isMalformed4(int b2, int b3, int b4) { + return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 || + (b4 & 0xc0) != 0x80; + } + + private static boolean isMalformed4_2(int b1, int b2) { + return (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) || + (b1 == 0xf4 && (b2 & 0xf0) != 0x80) || + (b2 & 0xc0) != 0x80; + } + + private static boolean isMalformed4_3(int b3) { + return (b3 & 0xc0) != 0x80; + } + + // for nb == 3/4 + private static int malformedN(byte[] src, int sp, int nb) { + if (nb == 3) { + int b1 = src[sp++]; + int b2 = src[sp++]; // no need to lookup b3 + return ((b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) || + isNotContinuation(b2)) ? 1 : 2; + } else if (nb == 4) { // we don't care the speed here + int b1 = src[sp++] & 0xff; + int b2 = src[sp++] & 0xff; + if (b1 > 0xf4 || + (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) || + (b1 == 0xf4 && (b2 & 0xf0) != 0x80) || + isNotContinuation(b2)) + return 1; + if (isNotContinuation(src[sp++])) + return 2; + return 3; + } + assert false; + return -1; + } + + private static char repl = '\ufffd'; + + StringCoding.Result decode(byte[] src, int sp, int len) { + return decode(src, sp, len, result); + } + + static StringCoding.Result decode(byte[] src, int sp, int len, + StringCoding.Result ret) { + int sl = sp + len; + byte[] dst = new byte[len]; + int dp = 0; + if (COMPACT_STRINGS) { // Latin1 only loop + while (sp < sl) { + int b1 = src[sp]; + if (b1 >= 0) { + dst[dp++] = (byte)b1; + sp++; + continue; + } + if ((b1 == (byte)0xc2 || b1 == (byte)0xc3) && + sp + 1 < sl) { + int b2 = src[sp + 1]; + if (!isNotContinuation(b2)) { + dst[dp++] = (byte)(((b1 << 6) ^ b2)^ + (((byte) 0xC0 << 6) ^ + ((byte) 0x80 << 0))); + sp += 2; + continue; + } + } + // anything not a latin1, including the repl + // we have to go with the utf16 + break; + } + if (sp == sl) { + if (dp != dst.length) { + dst = Arrays.copyOf(dst, dp); + } + return ret.with(dst, LATIN1); + } + } + if (dp == 0) { + dst = new byte[len << 1]; + } else { + byte[] buf = new byte[len << 1]; + StringLatin1.inflate(dst, 0, buf, 0, dp); + dst = buf; + } + while (sp < sl) { + int b1 = src[sp++]; + if (b1 >= 0) { + putChar(dst, dp++, (char) b1); + } else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) { + if (sp < sl) { + int b2 = src[sp++]; + if (isNotContinuation(b2)) { + putChar(dst, dp++, repl); + sp--; + } else { + putChar(dst, dp++, (char)(((b1 << 6) ^ b2)^ + (((byte) 0xC0 << 6) ^ + ((byte) 0x80 << 0)))); + } + continue; + } + putChar(dst, dp++, repl); + break; + } else if ((b1 >> 4) == -2) { + if (sp + 1 < sl) { + int b2 = src[sp++]; + int b3 = src[sp++]; + if (isMalformed3(b1, b2, b3)) { + putChar(dst, dp++, repl); + sp -= 3; + sp += malformedN(src, sp, 3); + } else { + char c = (char)((b1 << 12) ^ + (b2 << 6) ^ + (b3 ^ + (((byte) 0xE0 << 12) ^ + ((byte) 0x80 << 6) ^ + ((byte) 0x80 << 0)))); + putChar(dst, dp++, isSurrogate(c) ? repl : c); + } + continue; + } + if (sp < sl && isMalformed3_2(b1, src[sp])) { + putChar(dst, dp++, repl); + continue; + } + putChar(dst, dp++, repl); + break; + } else if ((b1 >> 3) == -2) { + if (sp + 2 < sl) { + int b2 = src[sp++]; + int b3 = src[sp++]; + int b4 = src[sp++]; + int uc = ((b1 << 18) ^ + (b2 << 12) ^ + (b3 << 6) ^ + (b4 ^ + (((byte) 0xF0 << 18) ^ + ((byte) 0x80 << 12) ^ + ((byte) 0x80 << 6) ^ + ((byte) 0x80 << 0)))); + if (isMalformed4(b2, b3, b4) || + !isSupplementaryCodePoint(uc)) { // shortest form check + putChar(dst, dp++, repl); + sp -= 4; + sp += malformedN(src, sp, 4); + } else { + putChar(dst, dp++, highSurrogate(uc)); + putChar(dst, dp++, lowSurrogate(uc)); + } + continue; + } + b1 &= 0xff; + if (b1 > 0xf4 || + sp < sl && isMalformed4_2(b1, src[sp] & 0xff)) { + putChar(dst, dp++, repl); + continue; + } + sp++; + putChar(dst, dp++, repl); + if (sp < sl && isMalformed4_3(src[sp])) { + continue; + } + break; + } else { + putChar(dst, dp++, repl); + } + } + if (dp != len) { + dst = Arrays.copyOf(dst, dp << 1); + } + return ret.with(dst, UTF16); + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/StringLatin1.java b/jdk/src/java.base/share/classes/java/lang/StringLatin1.java new file mode 100644 index 0000000000000000000000000000000000000000..eb8ddc651219965fc301a3de1d0683838d278994 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/StringLatin1.java @@ -0,0 +1,600 @@ +/* + * 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.util.Arrays; +import java.util.Locale; +import java.util.Objects; +import java.util.Spliterator; +import java.util.function.IntConsumer; +import java.util.stream.IntStream; +import jdk.internal.HotSpotIntrinsicCandidate; + +import static java.lang.String.LATIN1; +import static java.lang.String.UTF16; +import static java.lang.String.checkOffset; + +final class StringLatin1 { + + public static char charAt(byte[] value, int index) { + if (index < 0 || index >= value.length) { + throw new StringIndexOutOfBoundsException(index); + } + return (char)(value[index] & 0xff); + } + + public static boolean canEncode(int cp) { + return cp >>> 8 == 0; + } + + public static int length(byte[] value) { + return value.length; + } + + public static int codePointAt(byte[] value, int index, int end) { + return value[index] & 0xff; + } + + public static int codePointBefore(byte[] value, int index) { + return value[index - 1] & 0xff; + } + + public static int codePointCount(byte[] value, int beginIndex, int endIndex) { + return endIndex - beginIndex; + } + + public static char[] toChars(byte[] value) { + char[] dst = new char[value.length]; + inflate(value, 0, dst, 0, value.length); + return dst; + } + + public static byte[] inflate(byte[] value, int off, int len) { + byte[] ret = StringUTF16.newBytesFor(len); + inflate(value, off, ret, 0, len); + return ret; + } + + public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) { + inflate(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); + } + + public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) { + System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); + } + + @HotSpotIntrinsicCandidate + public static boolean equals(byte[] value, byte[] other) { + if (value.length == other.length) { + for (int i = 0; i < value.length; i++) { + if (value[i] != other[i]) { + return false; + } + } + return true; + } + return false; + } + + @HotSpotIntrinsicCandidate + public static int compareTo(byte[] value, byte[] other) { + int len1 = value.length; + int len2 = other.length; + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + if (value[k] != other[k]) { + return getChar(value, k) - getChar(other, k); + } + } + return len1 - len2; + } + + @HotSpotIntrinsicCandidate + public static int compareToUTF16(byte[] value, byte[] other) { + int len1 = length(value); + int len2 = StringUTF16.length(other); + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + char c1 = getChar(value, k); + char c2 = StringUTF16.getChar(other, k); + if (c1 != c2) { + return c1 - c2; + } + } + return len1 - len2; + } + + public static int hashCode(byte[] value) { + int h = 0; + for (byte v : value) { + h = 31 * h + (v & 0xff); + } + return h; + } + + public static int indexOf(byte[] value, int ch, int fromIndex) { + if (!canEncode(ch)) { + return -1; + } + int max = value.length; + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= max) { + // Note: fromIndex might be near -1>>>1. + return -1; + } + byte c = (byte)ch; + for (int i = fromIndex; i < max; i++) { + if (value[i] == c) { + return i; + } + } + return -1; + } + + @HotSpotIntrinsicCandidate + public static int indexOf(byte[] value, byte[] str) { + if (str.length == 0) { + return 0; + } + if (value.length == 0) { + return -1; + } + return indexOf(value, value.length, str, str.length, 0); + } + + @HotSpotIntrinsicCandidate + public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) { + byte first = str[0]; + int max = (valueCount - strCount); + for (int i = fromIndex; i <= max; i++) { + // Look for first character. + if (value[i] != first) { + while (++i <= max && value[i] != first); + } + // Found first character, now look at the rest of value + if (i <= max) { + int j = i + 1; + int end = j + strCount - 1; + for (int k = 1; j < end && value[j] == str[k]; j++, k++); + if (j == end) { + // Found whole string. + return i; + } + } + } + return -1; + } + + public static int lastIndexOf(byte[] src, int srcCount, + byte[] tgt, int tgtCount, int fromIndex) { + int min = tgtCount - 1; + int i = min + fromIndex; + int strLastIndex = tgtCount - 1; + char strLastChar = (char)(tgt[strLastIndex] & 0xff); + + startSearchForLastChar: + while (true) { + while (i >= min && (src[i] & 0xff) != strLastChar) { + i--; + } + if (i < min) { + return -1; + } + int j = i - 1; + int start = j - strLastIndex; + int k = strLastIndex - 1; + while (j > start) { + if ((src[j--] & 0xff) != (tgt[k--] & 0xff)) { + i--; + continue startSearchForLastChar; + } + } + return start + 1; + } + } + + public static int lastIndexOf(final byte[] value, int ch, int fromIndex) { + if (!canEncode(ch)) { + return -1; + } + int off = Math.min(fromIndex, value.length - 1); + for (; off >= 0; off--) { + if (value[off] == (byte)ch) { + return off; + } + } + return -1; + } + + public static String replace(byte[] value, char oldChar, char newChar) { + if (canEncode(oldChar)) { + int len = value.length; + int i = -1; + while (++i < len) { + if (value[i] == (byte)oldChar) { + break; + } + } + if (i < len) { + if (canEncode(newChar)) { + byte buf[] = new byte[len]; + for (int j = 0; j < i; j++) { // TBD arraycopy? + buf[j] = value[j]; + } + while (i < len) { + byte c = value[i]; + buf[i] = (c == (byte)oldChar) ? (byte)newChar : c; + i++; + } + return new String(buf, LATIN1); + } else { + byte[] buf = StringUTF16.newBytesFor(len); + // inflate from latin1 to UTF16 + inflate(value, 0, buf, 0, i); + while (i < len) { + char c = (char)(value[i] & 0xff); + StringUTF16.putChar(buf, i, (c == oldChar) ? newChar : c); + i++; + } + return new String(buf, UTF16); + } + } + } + return null; // for string to return this; + } + + // case insensitive + public static boolean regionMatchesCI(byte[] value, int toffset, + byte[] other, int ooffset, int len) { + int last = toffset + len; + while (toffset < last) { + char c1 = (char)(value[toffset++] & 0xff); + char c2 = (char)(other[ooffset++] & 0xff); + if (c1 == c2) { + continue; + } + char u1 = Character.toUpperCase(c1); + char u2 = Character.toUpperCase(c2); + if (u1 == u2) { + continue; + } + if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { + continue; + } + return false; + } + return true; + } + + public static boolean regionMatchesCI_UTF16(byte[] value, int toffset, + byte[] other, int ooffset, int len) { + int last = toffset + len; + while (toffset < last) { + char c1 = (char)(value[toffset++] & 0xff); + char c2 = StringUTF16.getChar(other, ooffset++); + if (c1 == c2) { + continue; + } + char u1 = Character.toUpperCase(c1); + char u2 = Character.toUpperCase(c2); + if (u1 == u2) { + continue; + } + if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { + continue; + } + return false; + } + return true; + } + + public static String toLowerCase(String str, byte[] value, Locale locale) { + if (locale == null) { + throw new NullPointerException(); + } + int first; + final int len = value.length; + // Now check if there are any characters that need to be changed, or are surrogate + for (first = 0 ; first < len; first++) { + int cp = value[first] & 0xff; + if (cp != Character.toLowerCase(cp)) { // no need to check Character.ERROR + break; + } + } + if (first == len) + return str; + String lang = locale.getLanguage(); + if (lang == "tr" || lang == "az" || lang == "lt") { + return toLowerCaseEx(str, value, first, locale, true); + } + byte[] result = new byte[len]; + System.arraycopy(value, 0, result, 0, first); // Just copy the first few + // lowerCase characters. + for (int i = first; i < len; i++) { + int cp = value[i] & 0xff; + cp = Character.toLowerCase(cp); + if (!canEncode(cp)) { // not a latin1 character + return toLowerCaseEx(str, value, first, locale, false); + } + result[i] = (byte)cp; + } + return new String(result, LATIN1); + } + + private static String toLowerCaseEx(String str, byte[] value, + int first, Locale locale, boolean localeDependent) + { + byte[] result = StringUTF16.newBytesFor(value.length); + int resultOffset = 0; + for (int i = 0; i < first; i++) { + StringUTF16.putChar(result, resultOffset++, value[i] & 0xff); + } + for (int i = first; i < value.length; i++) { + int srcChar = value[i] & 0xff; + int lowerChar; + char[] lowerCharArray; + if (localeDependent) { + lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale); + } else { + lowerChar = Character.toLowerCase(srcChar); + } + if (Character.isBmpCodePoint(lowerChar)) { // Character.ERROR is not a bmp + StringUTF16.putChar(result, resultOffset++, lowerChar); + } else { + if (lowerChar == Character.ERROR) { + lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale); + } else { + lowerCharArray = Character.toChars(lowerChar); + } + /* Grow result if needed */ + int mapLen = lowerCharArray.length; + if (mapLen > 1) { + byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1); + System.arraycopy(result, 0, result2, 0, resultOffset << 1); + result = result2; + } + for (int x = 0; x < mapLen; ++x) { + StringUTF16.putChar(result, resultOffset++, lowerCharArray[x]); + } + } + } + return StringUTF16.newString(result, 0, resultOffset); + } + + public static String toUpperCase(String str, byte[] value, Locale locale) { + if (locale == null) { + throw new NullPointerException(); + } + int first; + final int len = value.length; + + // Now check if there are any characters that need to be changed, or are surrogate + for (first = 0 ; first < len; first++ ) { + int cp = value[first] & 0xff; + if (cp != Character.toUpperCaseEx(cp)) { // no need to check Character.ERROR + break; + } + } + if (first == len) { + return str; + } + String lang = locale.getLanguage(); + if (lang == "tr" || lang == "az" || lang == "lt") { + return toUpperCaseEx(str, value, first, locale, true); + } + byte[] result = new byte[len]; + System.arraycopy(value, 0, result, 0, first); // Just copy the first few + // upperCase characters. + for (int i = first; i < len; i++) { + int cp = value[i] & 0xff; + cp = Character.toUpperCaseEx(cp); + if (!canEncode(cp)) { // not a latin1 character + return toUpperCaseEx(str, value, first, locale, false); + } + result[i] = (byte)cp; + } + return new String(result, LATIN1); + } + + private static String toUpperCaseEx(String str, byte[] value, + int first, Locale locale, boolean localeDependent) + { + byte[] result = StringUTF16.newBytesFor(value.length); + int resultOffset = 0; + for (int i = 0; i < first; i++) { + StringUTF16.putChar(result, resultOffset++, value[i] & 0xff); + } + for (int i = first; i < value.length; i++) { + int srcChar = value[i] & 0xff; + int upperChar; + char[] upperCharArray; + if (localeDependent) { + upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale); + } else { + upperChar = Character.toUpperCaseEx(srcChar); + } + if (Character.isBmpCodePoint(upperChar)) { + StringUTF16.putChar(result, resultOffset++, upperChar); + } else { + if (upperChar == Character.ERROR) { + if (localeDependent) { + upperCharArray = + ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale); + } else { + upperCharArray = Character.toUpperCaseCharArray(srcChar); + } + } else { + upperCharArray = Character.toChars(upperChar); + } + /* Grow result if needed */ + int mapLen = upperCharArray.length; + if (mapLen > 1) { + byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1); + System.arraycopy(result, 0, result2, 0, resultOffset << 1); + result = result2; + } + for (int x = 0; x < mapLen; ++x) { + StringUTF16.putChar(result, resultOffset++, upperCharArray[x]); + } + } + } + return StringUTF16.newString(result, 0, resultOffset); + } + + public static String trim(byte[] value) { + int len = value.length; + int st = 0; + while ((st < len) && ((value[st] & 0xff) <= ' ')) { + st++; + } + while ((st < len) && ((value[len - 1] & 0xff) <= ' ')) { + len--; + } + return ((st > 0) || (len < value.length)) ? + newString(value, st, len - st) : null; + } + + public static void putChar(byte[] val, int index, int c) { + //assert (canEncode(c)); + val[index] = (byte)(c); + } + + public static char getChar(byte[] val, int index) { + return (char)(val[index] & 0xff); + } + + public static byte[] toBytes(int[] val, int off, int len) { + byte[] ret = new byte[len]; + for (int i = 0; i < len; i++) { + int cp = val[off++]; + if (!canEncode(cp)) { + return null; + } + ret[i] = (byte)cp; + } + return ret; + } + + public static byte[] toBytes(char c) { + return new byte[] { (byte)c }; + } + + public static String newString(byte[] val, int index, int len) { + return new String(Arrays.copyOfRange(val, index, index + len), + LATIN1); + } + + public static void fillNull(byte[] val, int index, int end) { + Arrays.fill(val, index, end, (byte)0); + } + + // inflatedCopy byte[] -> char[] + @HotSpotIntrinsicCandidate + private static void inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) { + for (int i = 0; i < len; i++) { + dst[dstOff++] = (char)(src[srcOff++] & 0xff); + } + } + + // inflatedCopy byte[] -> byte[] + @HotSpotIntrinsicCandidate + public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { + for (int i = 0; i < len; i++) { + StringUTF16.putChar(dst, dstOff++, src[srcOff++] & 0xff); + } + } + + static class CharsSpliterator implements Spliterator.OfInt { + private final byte[] array; + private int index; // current index, modified on advance/split + private final int fence; // one past last index + private final int cs; + + CharsSpliterator(byte[] array, int acs) { + this(array, 0, array.length, acs); + } + + CharsSpliterator(byte[] array, int origin, int fence, int acs) { + this.array = array; + this.index = origin; + this.fence = fence; + this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED + | Spliterator.SUBSIZED; + } + + @Override + public OfInt trySplit() { + int lo = index, mid = (lo + fence) >>> 1; + return (lo >= mid) + ? null + : new CharsSpliterator(array, lo, index = mid, cs); + } + + @Override + public void forEachRemaining(IntConsumer action) { + byte[] a; int i, hi; // hoist accesses and checks from loop + if (action == null) + throw new NullPointerException(); + if ((a = array).length >= (hi = fence) && + (i = index) >= 0 && i < (index = hi)) { + do { action.accept(a[i] & 0xff); } while (++i < hi); + } + } + + @Override + public boolean tryAdvance(IntConsumer action) { + if (action == null) + throw new NullPointerException(); + if (index >= 0 && index < fence) { + action.accept(array[index++] & 0xff); + return true; + } + return false; + } + + @Override + public long estimateSize() { return (long)(fence - index); } + + @Override + public int characteristics() { + return cs; + } + } + + //////////////////////////////////////////////////////////////// + + public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) { + checkOffset(srcEnd, val.length); + getChars(val, srcBegin, srcEnd, dst, dstBegin); + } + + public static void inflateSB(byte[] val, byte[] dst, int dstOff, int count) { + checkOffset(count, val.length); + checkOffset(dstOff + count, dst.length >> 1); // dst is utf16 + inflate(val, 0, dst, dstOff, count); + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/StringUTF16.java b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java new file mode 100644 index 0000000000000000000000000000000000000000..56550d77fc6cf77d05c282cd2ca1bbe54a866302 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java @@ -0,0 +1,971 @@ +/* + * 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.util.Arrays; +import java.util.Locale; +import java.util.Spliterator; +import java.util.function.IntConsumer; +import jdk.internal.HotSpotIntrinsicCandidate; + +import static java.lang.String.UTF16; +import static java.lang.String.LATIN1; +import static java.lang.String.checkIndex; +import static java.lang.String.checkOffset; + +final class StringUTF16 { + + public static byte[] newBytesFor(int len) { + if (len < 0) { + throw new NegativeArraySizeException(); + } + if (len > MAX_LENGTH) { + throw new OutOfMemoryError("UTF16 String size is " + len + + ", should be less than " + MAX_LENGTH); + } + return new byte[len << 1]; + } + + @HotSpotIntrinsicCandidate + public static void putChar(byte[] val, int index, int c) { + index <<= 1; + val[index++] = (byte)(c >> HI_BYTE_SHIFT); + val[index] = (byte)(c >> LO_BYTE_SHIFT); + } + + @HotSpotIntrinsicCandidate + public static char getChar(byte[] val, int index) { + index <<= 1; + return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) | + ((val[index] & 0xff) << LO_BYTE_SHIFT)); + } + + public static char charAt(byte[] value, int index) { + if (index < 0 || index >= value.length >> 1) { + throw new StringIndexOutOfBoundsException(index); + } + return getChar(value, index); + } + + public static int length(byte[] value) { + return value.length >> 1; + } + + public static int codePointAt(byte[] value, int index, int end) { + char c1 = getChar(value, index); + if (Character.isHighSurrogate(c1) && ++index < end) { + char c2 = getChar(value, index); + if (Character.isLowSurrogate(c2)) { + return Character.toCodePoint(c1, c2); + } + } + return c1; + } + + public static int codePointBefore(byte[] value, int index) { + char c2 = getChar(value, --index); + if (Character.isLowSurrogate(c2) && index > 0) { + char c1 = getChar(value, --index); + if (Character.isHighSurrogate(c1)) { + return Character.toCodePoint(c1, c2); + } + } + return c2; + } + + public static int codePointCount(byte[] value, int beginIndex, int endIndex) { + int count = endIndex - beginIndex; + for (int i = beginIndex; i < endIndex; ) { + if (Character.isHighSurrogate(getChar(value, i++)) && + i < endIndex && + Character.isLowSurrogate(getChar(value, i))) { + count--; + i++; + } + } + return count; + } + + public static char[] toChars(byte[] value) { + char[] dst = new char[value.length >> 1]; + getChars(value, 0, dst.length, dst, 0); + return dst; + } + + @HotSpotIntrinsicCandidate + public static byte[] toBytes(char[] value, int off, int len) { + byte[] val = newBytesFor(len); + for (int i = 0; i < len; i++) { + putChar(val, i, value[off++]); + } + return val; + } + + public static byte[] compress(char[] val, int off, int len) { + byte[] ret = new byte[len]; + if (compress(val, off, ret, 0, len) == len) { + return ret; + } + return null; + } + + public static byte[] compress(byte[] val, int off, int len) { + byte[] ret = new byte[len]; + if (compress(val, off, ret, 0, len) == len) { + return ret; + } + return null; + } + + // compressedCopy char[] -> byte[] + @HotSpotIntrinsicCandidate + private static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) { + for (int i = 0; i < len; i++) { + int c = src[srcOff++]; + if (c >>> 8 != 0) { + return 0; + } + dst[dstOff++] = (byte)c; + } + return len; + } + + // compressedCopy byte[] -> byte[] + @HotSpotIntrinsicCandidate + public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { + for (int i = 0; i < len; i++) { + int c = getChar(src, srcOff++); + if (c >>> 8 != 0) { + return 0; + } + dst[dstOff++] = (byte)c; + } + return len; + } + + public static byte[] toBytes(int[] val, int index, int len) { + final int end = index + len; + // Pass 1: Compute precise size of char[] + int n = len; + for (int i = index; i < end; i++) { + int cp = val[i]; + if (Character.isBmpCodePoint(cp)) + continue; + else if (Character.isValidCodePoint(cp)) + n++; + else throw new IllegalArgumentException(Integer.toString(cp)); + } + // Pass 2: Allocate and fill in <high, low> pair + byte[] buf = newBytesFor(n); + for (int i = index, j = 0; i < end; i++, j++) { + int cp = val[i]; + if (Character.isBmpCodePoint(cp)) { + putChar(buf, j, cp); + } else { + putChar(buf, j++, Character.highSurrogate(cp)); + putChar(buf, j, Character.lowSurrogate(cp)); + } + } + return buf; + } + + public static byte[] toBytes(char c) { + byte[] result = new byte[2]; + putChar(result, 0, c); + return result; + } + + @HotSpotIntrinsicCandidate + public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) { + for (int i = srcBegin; i < srcEnd; i++) { + dst[dstBegin++] = getChar(value, i); + } + } + + /* @see java.lang.String.getBytes(int, int, byte[], int) */ + public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) { + srcBegin <<= 1; + srcEnd <<= 1; + for (int i = srcBegin + (1 >> LO_BYTE_SHIFT); i < srcEnd; i += 2) { + dst[dstBegin++] = value[i]; + } + } + + @HotSpotIntrinsicCandidate + public static boolean equals(byte[] value, byte[] other) { + if (value.length == other.length) { + int len = value.length >> 1; + for (int i = 0; i < len; i++) { + if (getChar(value, i) != getChar(other, i)) { + return false; + } + } + return true; + } + return false; + } + + @HotSpotIntrinsicCandidate + public static int compareTo(byte[] value, byte[] other) { + int len1 = length(value); + int len2 = length(other); + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + char c1 = getChar(value, k); + char c2 = getChar(other, k); + if (c1 != c2) { + return c1 - c2; + } + } + return len1 - len2; + } + + @HotSpotIntrinsicCandidate + public static int compareToLatin1(byte[] value, byte[] other) { + int len1 = length(value); + int len2 = StringLatin1.length(other); + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + char c1 = getChar(value, k); + char c2 = StringLatin1.getChar(other, k); + if (c1 != c2) { + return c1 - c2; + } + } + return len1 - len2; + } + + public static int hashCode(byte[] value) { + int h = 0; + int length = value.length >> 1; + for (int i = 0; i < length; i++) { + h = 31 * h + getChar(value, i); + } + return h; + } + + public static int indexOf(byte[] value, int ch, int fromIndex) { + int max = value.length >> 1; + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= max) { + // Note: fromIndex might be near -1>>>1. + return -1; + } + if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + // handle most cases here (ch is a BMP code point or a + // negative value (invalid code point)) + return indexOfChar(value, ch, fromIndex, max); + } else { + return indexOfSupplementary(value, ch, fromIndex, max); + } + } + + @HotSpotIntrinsicCandidate + public static int indexOf(byte[] value, byte[] str) { + if (str.length == 0) { + return 0; + } + if (value.length == 0) { + return -1; + } + return indexOf(value, length(value), str, length(str), 0); + } + + @HotSpotIntrinsicCandidate + public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) { + char first = getChar(str, 0); + int max = (valueCount - strCount); + for (int i = fromIndex; i <= max; i++) { + // Look for first character. + if (getChar(value, i) != first) { + while (++i <= max && getChar(value, i) != first); + } + // Found first character, now look at the rest of value + if (i <= max) { + int j = i + 1; + int end = j + strCount - 1; + for (int k = 1; j < end && getChar(value, j) == getChar(str, k); j++, k++); + if (j == end) { + // Found whole string. + return i; + } + } + } + return -1; + } + + /** + * Handles indexOf Latin1 substring in UTF16 string. + */ + @HotSpotIntrinsicCandidate + public static int indexOfLatin1(byte[] value, byte[] str) { + if (str.length == 0) { + return 0; + } + if (value.length == 0) { + return -1; + } + return indexOfLatin1(value, length(value), str, str.length, 0); + } + + @HotSpotIntrinsicCandidate + public static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) { + char first = (char)(tgt[0] & 0xff); + int max = (srcCount - tgtCount); + for (int i = fromIndex; i <= max; i++) { + // Look for first character. + if (getChar(src, i) != first) { + while (++i <= max && getChar(src, i) != first); + } + // Found first character, now look at the rest of v2 + if (i <= max) { + int j = i + 1; + int end = j + tgtCount - 1; + for (int k = 1; + j < end && getChar(src, j) == (tgt[k] & 0xff); + j++, k++); + if (j == end) { + // Found whole string. + return i; + } + } + } + return -1; + } + + @HotSpotIntrinsicCandidate + private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) { + for (int i = fromIndex; i < max; i++) { + if (getChar(value, i) == ch) { + return i; + } + } + return -1; + } + + /** + * Handles (rare) calls of indexOf with a supplementary character. + */ + private static int indexOfSupplementary(byte[] value, int ch, int fromIndex, int max) { + if (Character.isValidCodePoint(ch)) { + final char hi = Character.highSurrogate(ch); + final char lo = Character.lowSurrogate(ch); + for (int i = fromIndex; i < max - 1; i++) { + if (getChar(value, i) == hi && getChar(value, i + 1 ) == lo) { + return i; + } + } + } + return -1; + } + + public static int lastIndexOf(byte[] src, int srcCount, + byte[] tgt, int tgtCount, int fromIndex) { + int min = tgtCount - 1; + int i = min + fromIndex; + int strLastIndex = tgtCount - 1; + char strLastChar = getChar(tgt, strLastIndex); + + startSearchForLastChar: + while (true) { + while (i >= min && getChar(src, i) != strLastChar) { + i--; + } + if (i < min) { + return -1; + } + int j = i - 1; + int start = j - strLastIndex; + int k = strLastIndex - 1; + while (j > start) { + if (getChar(src, j--) != getChar(tgt, k--)) { + i--; + continue startSearchForLastChar; + } + } + return start + 1; + } + } + + public static int lastIndexOf(byte[] value, int ch, int fromIndex) { + if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + // handle most cases here (ch is a BMP code point or a + // negative value (invalid code point)) + int i = Math.min(fromIndex, (value.length >> 1) - 1); + for (; i >= 0; i--) { + if (getChar(value, i) == ch) { + return i; + } + } + return -1; + } else { + return lastIndexOfSupplementary(value, ch, fromIndex); + } + } + + /** + * Handles (rare) calls of lastIndexOf with a supplementary character. + */ + private static int lastIndexOfSupplementary(final byte[] value, int ch, int fromIndex) { + if (Character.isValidCodePoint(ch)) { + char hi = Character.highSurrogate(ch); + char lo = Character.lowSurrogate(ch); + int i = Math.min(fromIndex, (value.length >> 1) - 2); + for (; i >= 0; i--) { + if (getChar(value, i) == hi && getChar(value, i + 1) == lo) { + return i; + } + } + } + return -1; + } + + public static String replace(byte[] value, char oldChar, char newChar) { + int len = value.length >> 1; + int i = -1; + while (++i < len) { + if (getChar(value, i) == oldChar) { + break; + } + } + if (i < len) { + byte buf[] = new byte[value.length]; + for (int j = 0; j < i; j++) { + putChar(buf, j, getChar(value, j)); // TBD:arraycopy? + } + while (i < len) { + char c = getChar(value, i); + putChar(buf, i, c == oldChar ? newChar : c); + i++; + } + // Check if we should try to compress to latin1 + if (String.COMPACT_STRINGS && + !StringLatin1.canEncode(oldChar) && + StringLatin1.canEncode(newChar)) { + byte[] val = compress(buf, 0, len); + if (val != null) { + return new String(val, LATIN1); + } + } + return new String(buf, UTF16); + } + return null; + } + + public static boolean regionMatchesCI(byte[] value, int toffset, + byte[] other, int ooffset, int len) { + int last = toffset + len; + while (toffset < last) { + char c1 = getChar(value, toffset++); + char c2 = getChar(other, ooffset++); + if (c1 == c2) { + continue; + } + // try converting both characters to uppercase. + // If the results match, then the comparison scan should + // continue. + char u1 = Character.toUpperCase(c1); + char u2 = Character.toUpperCase(c2); + if (u1 == u2) { + continue; + } + // Unfortunately, conversion to uppercase does not work properly + // for the Georgian alphabet, which has strange rules about case + // conversion. So we need to make one last check before + // exiting. + if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { + continue; + } + return false; + } + return true; + } + + public static boolean regionMatchesCI_Latin1(byte[] value, int toffset, + byte[] other, int ooffset, + int len) { + int last = toffset + len; + while (toffset < last) { + char c1 = getChar(value, toffset++); + char c2 = (char)(other[ooffset++] & 0xff); + if (c1 == c2) { + continue; + } + char u1 = Character.toUpperCase(c1); + char u2 = Character.toUpperCase(c2); + if (u1 == u2) { + continue; + } + if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { + continue; + } + return false; + } + return true; + } + + public static String toLowerCase(String str, byte[] value, Locale locale) { + if (locale == null) { + throw new NullPointerException(); + } + int first; + boolean hasSurr = false; + final int len = value.length >> 1; + + // Now check if there are any characters that need to be changed, or are surrogate + for (first = 0 ; first < len; first++) { + int cp = (int)getChar(value, first); + if (Character.isSurrogate((char)cp)) { + hasSurr = true; + break; + } + if (cp != Character.toLowerCase(cp)) { // no need to check Character.ERROR + break; + } + } + if (first == len) + return str; + byte[] result = new byte[value.length]; + System.arraycopy(value, 0, result, 0, first << 1); // Just copy the first few + // lowerCase characters. + String lang = locale.getLanguage(); + if (lang == "tr" || lang == "az" || lang == "lt") { + return toLowerCaseEx(str, value, result, first, locale, true); + } + if (hasSurr) { + return toLowerCaseEx(str, value, result, first, locale, false); + } + int bits = 0; + for (int i = first; i < len; i++) { + int cp = (int)getChar(value, i); + if (cp == '\u03A3' || // GREEK CAPITAL LETTER SIGMA + Character.isSurrogate((char)cp)) { + return toLowerCaseEx(str, value, result, i, locale, false); + } + if (cp == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE + return toLowerCaseEx(str, value, result, i, locale, true); + } + cp = Character.toLowerCase(cp); + if (!Character.isBmpCodePoint(cp)) { + return toLowerCaseEx(str, value, result, i, locale, false); + } + bits |= cp; + putChar(result, i, cp); + } + if (bits >>> 8 != 0) { + return new String(result, UTF16); + } else { + return newString(result, 0, len); + } + } + + private static String toLowerCaseEx(String str, byte[] value, + byte[] result, int first, Locale locale, + boolean localeDependent) { + int resultOffset = first; + int length = value.length >> 1; + int srcCount; + for (int i = first; i < length; i += srcCount) { + int srcChar = getChar(value, i); + int lowerChar; + char[] lowerCharArray; + srcCount = 1; + if (Character.isSurrogate((char)srcChar)) { + srcChar = codePointAt(value, i, length); + srcCount = Character.charCount(srcChar); + } + if (localeDependent || + srcChar == '\u03A3' || // GREEK CAPITAL LETTER SIGMA + srcChar == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE + lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale); + } else { + lowerChar = Character.toLowerCase(srcChar); + } + if (Character.isBmpCodePoint(lowerChar)) { // Character.ERROR is not a bmp + putChar(result, resultOffset++, lowerChar); + } else { + if (lowerChar == Character.ERROR) { + lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale); + } else { + lowerCharArray = Character.toChars(lowerChar); + } + /* Grow result if needed */ + int mapLen = lowerCharArray.length; + if (mapLen > srcCount) { + byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount); + System.arraycopy(result, 0, result2, 0, resultOffset << 1); + result = result2; + } + for (int x = 0; x < mapLen; ++x) { + putChar(result, resultOffset++, lowerCharArray[x]); + } + } + } + return newString(result, 0, resultOffset); + } + + public static String toUpperCase(String str, byte[] value, Locale locale) { + if (locale == null) { + throw new NullPointerException(); + } + int first; + boolean hasSurr = false; + final int len = value.length >> 1; + + // Now check if there are any characters that need to be changed, or are surrogate + for (first = 0 ; first < len; first++) { + int cp = (int)getChar(value, first); + if (Character.isSurrogate((char)cp)) { + hasSurr = true; + break; + } + if (cp != Character.toUpperCaseEx(cp)) { // no need to check Character.ERROR + break; + } + } + if (first == len) { + return str; + } + byte[] result = new byte[value.length]; + System.arraycopy(value, 0, result, 0, first << 1); // Just copy the first few + // upperCase characters. + String lang = locale.getLanguage(); + if (lang == "tr" || lang == "az" || lang == "lt") { + return toUpperCaseEx(str, value, result, first, locale, true); + } + if (hasSurr) { + return toUpperCaseEx(str, value, result, first, locale, false); + } + int bits = 0; + for (int i = first; i < len; i++) { + int cp = (int)getChar(value, i); + if (Character.isSurrogate((char)cp)) { + return toUpperCaseEx(str, value, result, i, locale, false); + } + cp = Character.toUpperCaseEx(cp); + if (!Character.isBmpCodePoint(cp)) { // Character.ERROR is not bmp + return toUpperCaseEx(str, value, result, i, locale, false); + } + bits |= cp; + putChar(result, i, cp); + } + if (bits >>> 8 != 0) { + return new String(result, UTF16); + } else { + return newString(result, 0, len); + } + } + + private static String toUpperCaseEx(String str, byte[] value, + byte[] result, int first, + Locale locale, boolean localeDependent) + { + int resultOffset = first; + int length = value.length >> 1; + int srcCount; + for (int i = first; i < length; i += srcCount) { + int srcChar = getChar(value, i); + int upperChar; + char[] upperCharArray; + srcCount = 1; + if (Character.isSurrogate((char)srcChar)) { + srcChar = codePointAt(value, i, length); + srcCount = Character.charCount(srcChar); + } + if (localeDependent) { + upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale); + } else { + upperChar = Character.toUpperCaseEx(srcChar); + } + if (Character.isBmpCodePoint(upperChar)) { + putChar(result, resultOffset++, upperChar); + } else { + if (upperChar == Character.ERROR) { + if (localeDependent) { + upperCharArray = + ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale); + } else { + upperCharArray = Character.toUpperCaseCharArray(srcChar); + } + } else { + upperCharArray = Character.toChars(upperChar); + } + /* Grow result if needed */ + int mapLen = upperCharArray.length; + if (mapLen > srcCount) { + byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount); + System.arraycopy(result, 0, result2, 0, resultOffset << 1); + result = result2; + } + for (int x = 0; x < mapLen; ++x) { + putChar(result, resultOffset++, upperCharArray[x]); + } + } + } + return newString(result, 0, resultOffset); + } + + public static String trim(byte[] value) { + int length = value.length >> 1; + int len = length; + int st = 0; + while (st < len && getChar(value, st) <= ' ') { + st++; + } + while (st < len && getChar(value, len - 1) <= ' ') { + len--; + } + return ((st > 0) || (len < length )) ? + new String(Arrays.copyOfRange(value, st << 1, len << 1), UTF16) : + null; + } + + public static void putChars(byte[] val, int index, char[] str, int off, int end) { + while (off < end) { + putChar(val, index++, str[off++]); + } + } + + public static String newString(byte[] val, int index, int len) { + if (String.COMPACT_STRINGS) { + byte[] buf = compress(val, index, len); + if (buf != null) { + return new String(buf, LATIN1); + } + } + int last = index + len; + return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16); + } + + public static void fillNull(byte[] val, int index, int end) { + Arrays.fill(val, index << 1, end << 1, (byte)0); + } + + static class CharsSpliterator implements Spliterator.OfInt { + private final byte[] array; + private int index; // current index, modified on advance/split + private final int fence; // one past last index + private final int cs; + + CharsSpliterator(byte[] array, int acs) { + this(array, 0, array.length >> 1, acs); + } + + CharsSpliterator(byte[] array, int origin, int fence, int acs) { + this.array = array; + this.index = origin; + this.fence = fence; + this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED + | Spliterator.SUBSIZED; + } + + @Override + public OfInt trySplit() { + int lo = index, mid = (lo + fence) >>> 1; + return (lo >= mid) + ? null + : new CharsSpliterator(array, lo, index = mid, cs); + } + + @Override + public void forEachRemaining(IntConsumer action) { + byte[] a; int i, hi; // hoist accesses and checks from loop + if (action == null) + throw new NullPointerException(); + if (((a = array).length >> 1) >= (hi = fence) && + (i = index) >= 0 && i < (index = hi)) { + do { action.accept(getChar(a, i)); } while (++i < hi); + } + } + + @Override + public boolean tryAdvance(IntConsumer action) { + if (action == null) + throw new NullPointerException(); + if (index >= 0 && index < fence) { + action.accept(getChar(array, index++)); + return true; + } + return false; + } + + @Override + public long estimateSize() { return (long)(fence - index); } + + @Override + public int characteristics() { + return cs; + } + } + + static class CodePointsSpliterator implements Spliterator.OfInt { + private final byte[] array; + private int index; // current index, modified on advance/split + private final int fence; // one past last index + private final int cs; + + CodePointsSpliterator(byte[] array, int acs) { + this(array, 0, array.length >> 1, acs); + } + + CodePointsSpliterator(byte[] array, int origin, int fence, int acs) { + this.array = array; + this.index = origin; + this.fence = fence; + this.cs = acs | Spliterator.ORDERED; + } + + @Override + public OfInt trySplit() { + int lo = index, mid = (lo + fence) >>> 1; + if (lo >= mid) + return null; + + int midOneLess; + // If the mid-point intersects a surrogate pair + if (Character.isLowSurrogate(getChar(array, mid)) && + Character.isHighSurrogate(getChar(array, midOneLess = (mid -1)))) { + // If there is only one pair it cannot be split + if (lo >= midOneLess) + return null; + // Shift the mid-point to align with the surrogate pair + return new CodePointsSpliterator(array, lo, index = midOneLess, cs); + } + return new CodePointsSpliterator(array, lo, index = mid, cs); + } + + @Override + public void forEachRemaining(IntConsumer action) { + byte[] a; int i, hi; // hoist accesses and checks from loop + if (action == null) + throw new NullPointerException(); + if (((a = array).length >> 1) >= (hi = fence) && + (i = index) >= 0 && i < (index = hi)) { + do { + i = advance(a, i, hi, action); + } while (i < hi); + } + } + + @Override + public boolean tryAdvance(IntConsumer action) { + if (action == null) + throw new NullPointerException(); + if (index >= 0 && index < fence) { + index = advance(array, index, fence, action); + return true; + } + return false; + } + + // Advance one code point from the index, i, and return the next + // index to advance from + private static int advance(byte[] a, int i, int hi, IntConsumer action) { + char c1 = getChar(a, i++); + int cp = c1; + if (Character.isHighSurrogate(c1) && i < hi) { + char c2 = getChar(a, i); + if (Character.isLowSurrogate(c2)) { + i++; + cp = Character.toCodePoint(c1, c2); + } + } + action.accept(cp); + return i; + } + + @Override + public long estimateSize() { return (long)(fence - index); } + + @Override + public int characteristics() { + return cs; + } + } + + //////////////////////////////////////////////////////////////// + + public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) { + checkOffset(srcEnd, val.length >> 1); + getChars(val, srcBegin, srcEnd, dst, dstBegin); + } + + public static void putCharSB(byte[] val, int index, int c) { + checkIndex(index, val.length >> 1); + putChar(val, index, c); + } + + public static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) { + checkOffset(index + end - off, val.length >> 1); + putChars(val, index, ca, off, end); + } + + public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) { + checkOffset(index + end - off, val.length >> 1); + for (int i = off; i < end; i++) { + putChar(val, index++, s.charAt(i)); + } + } + + public static int codePointAtSB(byte[] val, int index, int end) { + checkOffset(end, val.length >> 1); + return codePointAt(val, index, end); + } + + public static int codePointBeforeSB(byte[] val, int index) { + checkOffset(index, val.length >> 1); + return codePointBefore(val, index); + } + + public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) { + checkOffset(endIndex, val.length >> 1); + return codePointCount(val, beginIndex, endIndex); + } + + public static String newStringSB(byte[] val, int index, int len) { + checkOffset(index + len, val.length >> 1); + return newString(val, index, len); + } + + //////////////////////////////////////////////////////////////// + + private static native boolean isBigEndian(); + + static final int HI_BYTE_SHIFT; + static final int LO_BYTE_SHIFT; + static { + if (isBigEndian()) { + HI_BYTE_SHIFT = 8; + LO_BYTE_SHIFT = 0; + } else { + HI_BYTE_SHIFT = 0; + LO_BYTE_SHIFT = 8; + } + } + + static final int MAX_LENGTH = Integer.MAX_VALUE >> 1; +} diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java index b8f9c52d19ffa7f4e9485bb51bc38847e7e9fbd3..f385d95c4c99cbe2821e87c4b010943cc356e3a4 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java @@ -34,14 +34,16 @@ import java.lang.invoke.LambdaForm.NamedFunction; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Field; import java.util.Arrays; -import java.util.HashMap; +import java.util.function.Function; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; +import jdk.internal.org.objectweb.asm.FieldVisitor; import sun.invoke.util.ValueConversions; import sun.invoke.util.Wrapper; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Type; /** * The flavor of method handle which emulates an invoke instruction @@ -217,7 +219,7 @@ import jdk.internal.org.objectweb.asm.Type; /*non-public*/ int fieldCount() { return 1; } - /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class); + /*non-public*/ static final SpeciesData SPECIES_DATA = new SpeciesData("L", Species_L.class); /*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) { return new Species_L(mt, lf, argL0); } @@ -335,7 +337,7 @@ import jdk.internal.org.objectweb.asm.Type; static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class); - private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) { + SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) { this.typeChars = types; this.typeCodes = basicTypes(types); this.clazz = clazz; @@ -355,26 +357,14 @@ import jdk.internal.org.objectweb.asm.Type; assert(!INIT_DONE); if (constructor() == null) { String types = typeChars; + CACHE.put(types, this); Factory.makeCtors(clazz, types, this.constructor); Factory.makeGetters(clazz, types, this.getters); Factory.makeNominalGetters(types, this.nominalGetters, this.getters); } } - private SpeciesData(String typeChars) { - // Placeholder only. - this.typeChars = typeChars; - this.typeCodes = basicTypes(typeChars); - this.clazz = null; - this.constructor = null; - this.getters = null; - this.nominalGetters = null; - this.extensions = null; - } - private boolean isPlaceholder() { return clazz == null; } - - private static final HashMap<String, SpeciesData> CACHE = new HashMap<>(); - static { CACHE.put("", EMPTY); } // make bootstrap predictable + private static final ConcurrentMap<String, SpeciesData> CACHE = new ConcurrentHashMap<>(); private static final boolean INIT_DONE; // set after <clinit> finishes... SpeciesData extendWith(byte type) { @@ -390,62 +380,52 @@ import jdk.internal.org.objectweb.asm.Type; } private static SpeciesData get(String types) { - // Acquire cache lock for query. - SpeciesData d = lookupCache(types); - if (!d.isPlaceholder()) - return d; - synchronized (d) { - // Use synch. on the placeholder to prevent multiple instantiation of one species. - // Creating this class forces a recursive call to getForClass. - if (lookupCache(types).isPlaceholder()) - Factory.generateConcreteBMHClass(types); - } - // Reacquire cache lock. - d = lookupCache(types); - // Class loading must have upgraded the cache. - assert(d != null && !d.isPlaceholder()); - return d; - } - static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) { - // clazz is a new class which is initializing its SPECIES_DATA field - return updateCache(types, new SpeciesData(types, clazz)); - } - private static synchronized SpeciesData lookupCache(String types) { - SpeciesData d = CACHE.get(types); - if (d != null) return d; - d = new SpeciesData(types); - assert(d.isPlaceholder()); - CACHE.put(types, d); - return d; - } - private static synchronized SpeciesData updateCache(String types, SpeciesData d) { - SpeciesData d2; - assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder()); - assert(!d.isPlaceholder()); - CACHE.put(types, d); - return d; + return CACHE.computeIfAbsent(types, new Function<String, SpeciesData>() { + @Override + public SpeciesData apply(String types) { + Class<? extends BoundMethodHandle> bmhcl = Factory.getConcreteBMHClass(types); + // SpeciesData instantiation may throw VirtualMachineError because of + // code cache overflow... + SpeciesData speciesData = new SpeciesData(types, bmhcl); + // CHM.computeIfAbsent ensures only one SpeciesData will be set + // successfully on the concrete BMH class if ever + Factory.setSpeciesDataToConcreteBMHClass(bmhcl, speciesData); + // the concrete BMH class is published via SpeciesData instance + // returned here only after it's SPECIES_DATA field is set + return speciesData; + } + }); } - static { - // pre-fill the BMH speciesdata cache with BMH's inner classes - final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class; + /** + * This is to be called when assertions are enabled. It checks whether SpeciesData for all of the statically + * defined species subclasses of BoundMethodHandle has been added to the SpeciesData cache. See below in the + * static initializer for + */ + static boolean speciesDataCachePopulated() { + Class<BoundMethodHandle> rootCls = BoundMethodHandle.class; try { for (Class<?> c : rootCls.getDeclaredClasses()) { if (rootCls.isAssignableFrom(c)) { final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class); - SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh); + SpeciesData d = Factory.getSpeciesDataFromConcreteBMHClass(cbmh); assert(d != null) : cbmh.getName(); assert(d.clazz == cbmh); - assert(d == lookupCache(d.typeChars)); + assert(CACHE.get(d.typeChars) == d); } } } catch (Throwable e) { throw newInternalError(e); } + return true; + } - for (SpeciesData d : CACHE.values()) { - d.initForBootstrap(); - } + static { + // Pre-fill the BMH species-data cache with EMPTY and all BMH's inner subclasses. + EMPTY.initForBootstrap(); + Species_L.SPECIES_DATA.initForBootstrap(); + // check that all static SpeciesData instances have been initialized + assert speciesDataCachePopulated(); // Note: Do not simplify this, because INIT_DONE must not be // a compile-time constant during bootstrapping. INIT_DONE = Boolean.TRUE; @@ -479,6 +459,7 @@ import jdk.internal.org.objectweb.asm.Type; static final String BMH_SIG = "L"+BMH+";"; static final String SPECIES_DATA = "java/lang/invoke/BoundMethodHandle$SpeciesData"; static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";"; + static final String STABLE_SIG = "Ljava/lang/invoke/Stable;"; static final String SPECIES_PREFIX_NAME = "Species_"; static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME; @@ -493,6 +474,26 @@ import jdk.internal.org.objectweb.asm.Type; static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" }; + static final ConcurrentMap<String, Class<? extends BoundMethodHandle>> CLASS_CACHE = new ConcurrentHashMap<>(); + + /** + * Get a concrete subclass of BMH for a given combination of bound types. + * + * @param types the type signature, wherein reference types are erased to 'L' + * @return the concrete BMH class + */ + static Class<? extends BoundMethodHandle> getConcreteBMHClass(String types) { + // CHM.computeIfAbsent ensures generateConcreteBMHClass is called + // only once per key. + return CLASS_CACHE.computeIfAbsent( + types, new Function<String, Class<? extends BoundMethodHandle>>() { + @Override + public Class<? extends BoundMethodHandle> apply(String types) { + return generateConcreteBMHClass(types); + } + }); + } + /** * Generate a concrete subclass of BMH for a given combination of bound types. * @@ -529,7 +530,7 @@ import jdk.internal.org.objectweb.asm.Type; * } * final SpeciesData speciesData() { return SPECIES_DATA; } * final int fieldCount() { return 3; } - * static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class); + * @Stable static SpeciesData SPECIES_DATA; // injected afterwards * static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) { * return new Species_LLI(mt, lf, argL0, argL1, argI2); * } @@ -568,7 +569,9 @@ import jdk.internal.org.objectweb.asm.Type; cw.visitSource(sourceFile, null); // emit static types and SPECIES_DATA fields - cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd(); + FieldVisitor fw = cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null); + fw.visitAnnotation(STABLE_SIG, true); + fw.visitEnd(); // emit bound argument fields for (int i = 0; i < types.length(); ++i) { @@ -694,17 +697,6 @@ import jdk.internal.org.objectweb.asm.Type; mv.visitEnd(); } - // emit class initializer - mv = cw.visitMethod(NOT_ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null); - mv.visitCode(); - mv.visitLdcInsn(types); - mv.visitLdcInsn(Type.getObjectType(className)); - mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG, false); - mv.visitFieldInsn(PUTSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); - mv.visitInsn(RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); - cw.visitEnd(); // load class @@ -715,7 +707,6 @@ import jdk.internal.org.objectweb.asm.Type; UNSAFE.defineClass(className, classFile, 0, classFile.length, BoundMethodHandle.class.getClassLoader(), null) .asSubclass(BoundMethodHandle.class); - UNSAFE.ensureClassInitialized(bmhClass); return bmhClass; } @@ -785,7 +776,7 @@ import jdk.internal.org.objectweb.asm.Type; // Auxiliary methods. // - static SpeciesData speciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) { + static SpeciesData getSpeciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) { try { Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA"); return (SpeciesData) F_SPECIES_DATA.get(null); @@ -794,6 +785,16 @@ import jdk.internal.org.objectweb.asm.Type; } } + static void setSpeciesDataToConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh, SpeciesData speciesData) { + try { + Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA"); + assert F_SPECIES_DATA.getDeclaredAnnotation(Stable.class) != null; + F_SPECIES_DATA.set(null, speciesData); + } catch (ReflectiveOperationException ex) { + throw newInternalError(ex); + } + } + /** * Field names in concrete BMHs adhere to this pattern: * arg + type + index diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java index c70b9db3097036233c3e2aa96501ef87424cab36..3c9e141461f8b4b2612d3de98b83721018b4a4cb 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -25,7 +25,7 @@ package java.lang.invoke; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import java.lang.reflect.Method; import java.util.Arrays; import sun.invoke.util.VerifyAccess; diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 5f821977c0f844b93349e38d785be75829196e46..9a43947d34e30ff0a62f5d07ba72f938ef04d80d 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -27,7 +27,7 @@ package java.lang.invoke; import jdk.internal.org.objectweb.asm.*; import sun.invoke.util.BytecodeDescriptor; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; import java.io.FilePermission; diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index bcfa877fbf10dc85aca94224948f5f7df10c3fbd..dda16ad9edafff1a1cb0ca665d14768882441bd0 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -775,7 +775,7 @@ class InvokerBytecodeGenerator { // Sample classes from each package we are willing to bind to statically: java.lang.Object.class, java.util.Arrays.class, - sun.misc.Unsafe.class + jdk.internal.misc.Unsafe.class //MethodHandle.class already covered }; diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java index 1f60038e1215ea42828b80132c4d206dcf76d87e..5f9580e17f4974a76604d2fe0ee394a36f82dd30 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java @@ -694,8 +694,11 @@ import java.util.Objects; @Override public int hashCode() { - return Objects.hash(clazz, getReferenceKind(), name, getType()); + // Avoid autoboxing getReferenceKind(), since this is used early and will force + // early initialization of Byte$ByteCache + return Objects.hash(clazz, new Byte(getReferenceKind()), name, getType()); } + @Override public boolean equals(Object that) { return (that instanceof MemberName && this.equals((MemberName)that)); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index 29bd6dbf51239487c6c2d8e983d26f65ee3395b6..f983b2d792a9fdd9a683c2ff4a3c3f2362423b0e 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -50,7 +50,7 @@ class MethodHandleNatives { static native int getMembers(Class<?> defc, String matchName, String matchSig, int matchFlags, Class<?> caller, int skip, MemberName[] results); - /// Field layout queries parallel to sun.misc.Unsafe: + /// Field layout queries parallel to jdk.internal.misc.Unsafe: static native long objectFieldOffset(MemberName self); // e.g., returns vmindex static native long staticFieldOffset(MemberName self); // e.g., returns vmindex static native Object staticFieldBase(MemberName self); // e.g., returns clazz diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java index aae6053acf2a001edc1b1285687942b2f2a8abff..c449f4cb59168855ea901c13c940bdddbf8aedfb 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -27,7 +27,7 @@ package java.lang.invoke; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * This class consists exclusively of static names internal to the diff --git a/jdk/src/java.base/share/classes/java/math/BigDecimal.java b/jdk/src/java.base/share/classes/java/math/BigDecimal.java index 7214950c489ca30609516536f7f0e0f21cc6a73c..a126e9339f112182070b5eef6af120b2f78bd782 100644 --- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java +++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java @@ -3726,12 +3726,12 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> { } private static class UnsafeHolder { - private static final sun.misc.Unsafe unsafe; + private static final jdk.internal.misc.Unsafe unsafe; private static final long intCompactOffset; private static final long intValOffset; static { try { - unsafe = sun.misc.Unsafe.getUnsafe(); + unsafe = jdk.internal.misc.Unsafe.getUnsafe(); intCompactOffset = unsafe.objectFieldOffset (BigDecimal.class.getDeclaredField("intCompact")); intValOffset = unsafe.objectFieldOffset diff --git a/jdk/src/java.base/share/classes/java/math/BigInteger.java b/jdk/src/java.base/share/classes/java/math/BigInteger.java index 80330c8c4e49d150459b895b89ae94e68e2a3ad2..4471de71198b687203d51c5846d228d5ac363a6a 100644 --- a/jdk/src/java.base/share/classes/java/math/BigInteger.java +++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java @@ -4526,12 +4526,12 @@ public class BigInteger extends Number implements Comparable<BigInteger> { // Support for resetting final fields while deserializing private static class UnsafeHolder { - private static final sun.misc.Unsafe unsafe; + private static final jdk.internal.misc.Unsafe unsafe; private static final long signumOffset; private static final long magOffset; static { try { - unsafe = sun.misc.Unsafe.getUnsafe(); + unsafe = jdk.internal.misc.Unsafe.getUnsafe(); signumOffset = unsafe.objectFieldOffset (BigInteger.class.getDeclaredField("signum")); magOffset = unsafe.objectFieldOffset diff --git a/jdk/src/java.base/share/classes/java/net/Inet6Address.java b/jdk/src/java.base/share/classes/java/net/Inet6Address.java index e51064fbd316aad62e71aaa9ad7158b0fa879494..0daac2f2b03210b12bf5f83716fb45049dc604aa 100644 --- a/jdk/src/java.base/share/classes/java/net/Inet6Address.java +++ b/jdk/src/java.base/share/classes/java/net/Inet6Address.java @@ -576,11 +576,11 @@ class Inet6Address extends InetAddress { }; private static final long FIELDS_OFFSET; - private static final sun.misc.Unsafe UNSAFE; + private static final jdk.internal.misc.Unsafe UNSAFE; static { try { - sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); FIELDS_OFFSET = unsafe.objectFieldOffset( Inet6Address.class.getDeclaredField("holder6")); UNSAFE = unsafe; diff --git a/jdk/src/java.base/share/classes/java/net/InetAddress.java b/jdk/src/java.base/share/classes/java/net/InetAddress.java index a2d89b25d31d1523cef1a11ffb39a3bb638bae4a..0878c57848b6d199792d0450e72ee287e38910c6 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -29,6 +29,7 @@ import java.util.NavigableSet; import java.util.Iterator; import java.util.List; import java.util.ArrayList; +import java.util.Objects; import java.util.ServiceLoader; import java.security.AccessController; import java.io.ObjectStreamException; @@ -733,7 +734,7 @@ class InetAddress implements java.io.Serializable { */ public String toString() { String hostName = holder().getHostName(); - return ((hostName != null) ? hostName : "") + return Objects.toString(hostName, "") + "/" + getHostAddress(); } @@ -1493,11 +1494,11 @@ class InetAddress implements java.io.Serializable { } private static final long FIELDS_OFFSET; - private static final sun.misc.Unsafe UNSAFE; + private static final jdk.internal.misc.Unsafe UNSAFE; static { try { - sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); FIELDS_OFFSET = unsafe.objectFieldOffset( InetAddress.class.getDeclaredField("holder") ); diff --git a/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java b/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java index 2bdfdc25102ba5eaa4003031c67db2d66f8b4b17..8e2a2fc925c18d9c21e9ec60716b2f3d62b35dc4 100644 --- a/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java @@ -303,10 +303,10 @@ public class InetSocketAddress } private static final long FIELDS_OFFSET; - private static final sun.misc.Unsafe UNSAFE; + private static final jdk.internal.misc.Unsafe UNSAFE; static { try { - sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); FIELDS_OFFSET = unsafe.objectFieldOffset( InetSocketAddress.class.getDeclaredField("holder")); UNSAFE = unsafe; diff --git a/jdk/src/java.base/share/classes/java/net/SocketOptions.java b/jdk/src/java.base/share/classes/java/net/SocketOptions.java index 82e98e990643d6f12febbf334973b221bb3c109a..c846bbb9b12c592430b142ddfd4f8afa2a73026c 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketOptions.java +++ b/jdk/src/java.base/share/classes/java/net/SocketOptions.java @@ -61,21 +61,21 @@ public interface SocketOptions { * If the requested option is binary, it can be set using this method by * a java.lang.Boolean: * <BR><PRE> - * s.setOption(TCP_NODELAY, new Boolean(true)); + * s.setOption(TCP_NODELAY, Boolean.TRUE); * // OK - enables TCP_NODELAY, a binary option * </PRE> * <BR> - * Any option can be disabled using this method with a Boolean(false): + * Any option can be disabled using this method with a Boolean.FALSE: * <BR><PRE> - * s.setOption(TCP_NODELAY, new Boolean(false)); + * s.setOption(TCP_NODELAY, Boolean.FALSE); * // OK - disables TCP_NODELAY - * s.setOption(SO_LINGER, new Boolean(false)); + * s.setOption(SO_LINGER, Boolean.FALSE); * // OK - disables SO_LINGER * </PRE> * <BR> * For an option that has a notion of on and off, and requires * a non-boolean parameter, setting its value to anything other than - * <I>Boolean(false)</I> implicitly enables it. + * <I>Boolean.FALSE</I> implicitly enables it. * <BR> * Throws SocketException if the option is unrecognized, * the socket is closed, or some low-level error occurred @@ -91,8 +91,8 @@ public interface SocketOptions { /** * Fetch the value of an option. - * Binary options will return java.lang.Boolean(true) - * if enabled, java.lang.Boolean(false) if disabled, e.g.: + * Binary options will return java.lang.Boolean.TRUE + * if enabled, java.lang.Boolean.FALSE if disabled, e.g.: * <BR><PRE> * SocketImpl s; * ... @@ -105,13 +105,13 @@ public interface SocketOptions { * <P> * For options that take a particular type as a parameter, * getOption(int) will return the parameter's value, else - * it will return java.lang.Boolean(false): + * it will return java.lang.Boolean.FALSE: * <PRE> * Object o = s.getOption(SO_LINGER); * if (o instanceof Integer) { * System.out.print("Linger time is " + ((Integer)o).intValue()); * } else { - * // the true type of o is java.lang.Boolean(false); + * // the true type of o is java.lang.Boolean.FALSE; * } * </PRE> * diff --git a/jdk/src/java.base/share/classes/java/net/URLConnection.java b/jdk/src/java.base/share/classes/java/net/URLConnection.java index bdc37963d6c21cbc61f7bae8f217a0abc04b4b62..544107828b946a2cb1ab7c9b47ed13b44e075d39 100644 --- a/jdk/src/java.base/share/classes/java/net/URLConnection.java +++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java @@ -32,6 +32,7 @@ import java.security.PrivilegedAction; import java.util.Hashtable; import java.util.Date; import java.util.Iterator; +import java.util.Objects; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.StringTokenizer; @@ -1250,7 +1251,7 @@ public abstract class URLConnection { if (handler != null) { ContentHandler h = handlers.putIfAbsent(contentType, handler); - return h != null ? h : handler; + return Objects.requireNonNullElse(h, handler); } try { @@ -1263,7 +1264,7 @@ public abstract class URLConnection { assert handler != null; ContentHandler h = handlers.putIfAbsent(contentType, handler); - return h != null ? h : handler; + return Objects.requireNonNullElse(h, handler); } /* diff --git a/jdk/src/java.base/share/classes/java/nio/Bits.java b/jdk/src/java.base/share/classes/java/nio/Bits.java index 803360ea132bb07c97be319ed60eaff721027830..526c71d3f8b65fae668be14f610bbec12d319e53 100644 --- a/jdk/src/java.base/share/classes/java/nio/Bits.java +++ b/jdk/src/java.base/share/classes/java/nio/Bits.java @@ -32,7 +32,7 @@ import java.util.concurrent.atomic.LongAdder; import jdk.internal.misc.JavaNioAccess; import jdk.internal.misc.JavaLangRefAccess; import jdk.internal.misc.SharedSecrets; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.misc.VM; /** diff --git a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index cf2cc29c8647bdaa0e499abb67483e801a90fca8..c2d8d8ea12e3acfde594b5efb158eb7cbc81055d 100644 --- a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template @@ -29,7 +29,7 @@ package java.nio; import java.io.FileDescriptor; import sun.misc.Cleaner; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.misc.VM; import sun.nio.ch.DirectBuffer; diff --git a/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template b/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template index c37901431fb0860ddd9d5c833ab9469d0202226b..9ca784b8a778066936679aebea7f50b9e1e52a19 100644 --- a/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template +++ b/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template @@ -27,7 +27,7 @@ package java.nio; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** #if[rw] @@ -477,7 +477,7 @@ class Heap$Type$Buffer$RW$ #if[rw] public float getFloat() { - int x = unsafe.getIntUnaligned(hb, byteOffset(nextPutIndex(4)), bigEndian); + int x = unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian); return Float.intBitsToFloat(x); } diff --git a/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java b/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java index 953a78b82067d901b5b3b0f3831fd53ee120fb85..a9c6005d28c765bbcc5190abc44d4c6982a9bd59 100644 --- a/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java +++ b/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java @@ -26,7 +26,7 @@ package java.nio; import java.io.FileDescriptor; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** diff --git a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java index 6766cb53c3de500442700ed57d8d8bb2643a550b..498ed3652133c5e5f1d6d1e01d3571880cccbe0b 100644 --- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java @@ -37,6 +37,7 @@ import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Set; import java.util.ServiceLoader; import java.util.ServiceConfigurationError; @@ -625,6 +626,7 @@ public abstract class Charset private final String name; // tickles a bug in oldjavac private final String[] aliases; // tickles a bug in oldjavac + private final String[] zeroAliases = new String[0]; private Set<String> aliasSet = null; /** @@ -642,7 +644,7 @@ public abstract class Charset */ protected Charset(String canonicalName, String[] aliases) { checkName(canonicalName); - String[] as = (aliases == null) ? new String[0] : aliases; + String[] as = Objects.requireNonNullElse(aliases, zeroAliases); for (int i = 0; i < as.length; i++) checkName(as[i]); this.name = canonicalName; diff --git a/jdk/src/java.base/share/classes/java/security/SecureRandom.java b/jdk/src/java.base/share/classes/java/security/SecureRandom.java index 2f8d734ac00f1ae2c10232bcccb0cf6d5936510b..a2a246f4a14cec6fd5aa0a8fbfb59b6bfc9cd98d 100644 --- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java +++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java @@ -419,7 +419,7 @@ public class SecureRandom extends java.util.Random { * @since 1.5 */ public String getAlgorithm() { - return (algorithm != null) ? algorithm : "unknown"; + return Objects.toString(algorithm, "unknown"); } /** diff --git a/jdk/src/java.base/share/classes/java/time/ZoneId.java b/jdk/src/java.base/share/classes/java/time/ZoneId.java index dd282d4a4c45fb7be1e7d6a2c1d02876d5d01d6d..bae99f601cceb7e657f9c1d4986dc18062df72da 100644 --- a/jdk/src/java.base/share/classes/java/time/ZoneId.java +++ b/jdk/src/java.base/share/classes/java/time/ZoneId.java @@ -310,8 +310,7 @@ public abstract class ZoneId implements Serializable { public static ZoneId of(String zoneId, Map<String, String> aliasMap) { Objects.requireNonNull(zoneId, "zoneId"); Objects.requireNonNull(aliasMap, "aliasMap"); - String id = aliasMap.get(zoneId); - id = (id != null ? id : zoneId); + String id = Objects.requireNonNullElse(aliasMap.get(zoneId), zoneId); return of(id); } diff --git a/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java b/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java index fbcdcec34724462f8d409ea64040f01f5d0afff6..5783f93ddf1d7abc066a034e00569e59c3ac6a3a 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java @@ -177,7 +177,7 @@ public interface Chronology extends Comparable<Chronology> { static Chronology from(TemporalAccessor temporal) { Objects.requireNonNull(temporal, "temporal"); Chronology obj = temporal.query(TemporalQueries.chronology()); - return (obj != null ? obj : IsoChronology.INSTANCE); + return Objects.requireNonNullElse(obj, IsoChronology.INSTANCE); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index 90c6108c2443a2ea38790084aeaca5ba1867eecf..441ac711110ec952a93660a7aa88d1021609aa9f 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -2892,7 +2892,8 @@ public final class DateTimeFormatterBuilder { @Override public String toString() { - return "ReducedValue(" + field + "," + minWidth + "," + maxWidth + "," + (baseDate != null ? baseDate : baseValue) + ")"; + return "ReducedValue(" + field + "," + minWidth + "," + maxWidth + + "," + Objects.requireNonNullElse(baseDate, baseValue) + ")"; } } @@ -3851,6 +3852,10 @@ public final class DateTimeFormatterBuilder { return parseOffsetBased(context, text, position, position + 2, OffsetIdPrinterParser.INSTANCE_ID_ZERO); } else if (context.charEquals(nextChar, 'G') && length >= position + 3 && context.charEquals(nextNextChar, 'M') && context.charEquals(text.charAt(position + 2), 'T')) { + if (length >= position + 4 && context.charEquals(text.charAt(position + 3), '0')) { + context.setParsed(ZoneId.of("GMT0")); + return position + 4; + } return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO); } } @@ -4328,7 +4333,7 @@ public final class DateTimeFormatterBuilder { private String getChronologyName(Chronology chrono, Locale locale) { String key = "calendarname." + chrono.getCalendarType(); String name = DateTimeTextProvider.getLocalizedResource(key, locale); - return name != null ? name : chrono.getId(); + return Objects.requireNonNullElseGet(name, () -> chrono.getId()); } } diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java b/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java index 543a317e92e80e2fc3eddc53512ad2683d0f15b1..310f6598fc97b027c82d069bd171ecdeda69f27f 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java @@ -146,7 +146,7 @@ final class DateTimePrintContext { if (overrideZone != null) { // if have zone and instant, calculation is simple, defaulting chrono if necessary if (temporal.isSupported(INSTANT_SECONDS)) { - Chronology chrono = (effectiveChrono != null ? effectiveChrono : IsoChronology.INSTANCE); + Chronology chrono = Objects.requireNonNullElse(effectiveChrono, IsoChronology.INSTANCE); return chrono.zonedDateTime(Instant.from(temporal), overrideZone); } // block changing zone on OffsetTime, and similar problem cases diff --git a/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java b/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java index 76528c4e7dd0c3b6fcd00eedaf90a032a5efaeea..73ebdf40abfda620ec358dc9282947a4cc3f313a 100644 --- a/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java +++ b/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.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 @@ -102,7 +102,7 @@ import sun.util.locale.provider.LocaleResources; * The complete date is expressed using three fields: * <ul> * <li>{@link #DAY_OF_QUARTER DAY_OF_QUARTER} - the day within the quarter, from 1 to 90, 91 or 92 - * <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the week within the week-based-year + * <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the quarter within the year, from 1 to 4 * <li>{@link ChronoField#YEAR YEAR} - the standard ISO year * </ul> * @@ -571,9 +571,6 @@ public final class IsoFields { //------------------------------------------------------------------------- private static final int[] QUARTER_DAYS = {0, 90, 181, 273, 0, 91, 182, 274}; - private static boolean isIso(TemporalAccessor temporal) { - return Chronology.from(temporal).equals(IsoChronology.INSTANCE); - } private static void ensureIso(TemporalAccessor temporal) { if (isIso(temporal) == false) { @@ -681,7 +678,7 @@ public final class IsoFields { @Override public boolean isSupportedBy(Temporal temporal) { - return temporal.isSupported(EPOCH_DAY); + return temporal.isSupported(EPOCH_DAY) && isIso(temporal); } @SuppressWarnings("unchecked") @@ -721,4 +718,8 @@ public final class IsoFields { return name; } } + + static boolean isIso(TemporalAccessor temporal) { + return Chronology.from(temporal).equals(IsoChronology.INSTANCE); + } } diff --git a/jdk/src/java.base/share/classes/java/util/Arrays.java b/jdk/src/java.base/share/classes/java/util/Arrays.java index f18180ac84d2f69da38adf32c091da8ab061a1ef..f172e508ca8e3fbb03c17995d220511660baec7c 100644 --- a/jdk/src/java.base/share/classes/java/util/Arrays.java +++ b/jdk/src/java.base/share/classes/java/util/Arrays.java @@ -2882,6 +2882,7 @@ public class Arrays { * @param a2 the other array to be tested for equality * @return {@code true} if the two arrays are equal */ + @HotSpotIntrinsicCandidate public static boolean equals(byte[] a, byte[] a2) { if (a==a2) return true; diff --git a/jdk/src/java.base/share/classes/java/util/Collections.java b/jdk/src/java.base/share/classes/java/util/Collections.java index fec21c29079bca0d4b6cf823d9e4c74c0b4eb983..5dcc7e8c6b00ada456033464b7de4a1697fbda2d 100644 --- a/jdk/src/java.base/share/classes/java/util/Collections.java +++ b/jdk/src/java.base/share/classes/java/util/Collections.java @@ -2090,7 +2090,8 @@ public class Collections { * through the returned set.<p> * * It is imperative that the user manually synchronize on the returned - * set when iterating over it: + * collection when traversing it via {@link Iterator}, {@link Spliterator} + * or {@link Stream}: * <pre> * Set s = Collections.synchronizedSet(new HashSet()); * ... @@ -2149,8 +2150,9 @@ public class Collections { * through the returned sorted set (or its views).<p> * * It is imperative that the user manually synchronize on the returned - * sorted set when iterating over it or any of its {@code subSet}, - * {@code headSet}, or {@code tailSet} views. + * sorted set when traversing it or any of its {@code subSet}, + * {@code headSet}, or {@code tailSet} views via {@link Iterator}, + * {@link Spliterator} or {@link Stream}: * <pre> * SortedSet s = Collections.synchronizedSortedSet(new TreeSet()); * ... @@ -2240,8 +2242,9 @@ public class Collections { * accomplished through the returned navigable set (or its views).<p> * * It is imperative that the user manually synchronize on the returned - * navigable set when iterating over it or any of its {@code subSet}, - * {@code headSet}, or {@code tailSet} views. + * navigable set when traversing it, or any of its {@code subSet}, + * {@code headSet}, or {@code tailSet} views, via {@link Iterator}, + * {@link Spliterator} or {@link Stream}: * <pre> * NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet()); * ... @@ -2355,7 +2358,8 @@ public class Collections { * through the returned list.<p> * * It is imperative that the user manually synchronize on the returned - * list when iterating over it: + * list when traversing it via {@link Iterator}, {@link Spliterator} + * or {@link Stream}: * <pre> * List list = Collections.synchronizedList(new ArrayList()); * ... @@ -2523,7 +2527,8 @@ public class Collections { * through the returned map.<p> * * It is imperative that the user manually synchronize on the returned - * map when iterating over any of its collection views: + * map when traversing any of its collection views via {@link Iterator}, + * {@link Spliterator} or {@link Stream}: * <pre> * Map m = Collections.synchronizedMap(new HashMap()); * ... @@ -2700,9 +2705,10 @@ public class Collections { * through the returned sorted map (or its views).<p> * * It is imperative that the user manually synchronize on the returned - * sorted map when iterating over any of its collection views, or the + * sorted map when traversing any of its collection views, or the * collections views of any of its {@code subMap}, {@code headMap} or - * {@code tailMap} views. + * {@code tailMap} views, via {@link Iterator}, {@link Spliterator} or + * {@link Stream}: * <pre> * SortedMap m = Collections.synchronizedSortedMap(new TreeMap()); * ... @@ -2797,9 +2803,10 @@ public class Collections { * accomplished through the returned navigable map (or its views).<p> * * It is imperative that the user manually synchronize on the returned - * navigable map when iterating over any of its collection views, or the + * navigable map when traversing any of its collection views, or the * collections views of any of its {@code subMap}, {@code headMap} or - * {@code tailMap} views. + * {@code tailMap} views, via {@link Iterator}, {@link Spliterator} or + * {@link Stream}: * <pre> * NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap()); * ... diff --git a/jdk/src/java.base/share/classes/java/util/Formatter.java b/jdk/src/java.base/share/classes/java/util/Formatter.java index d8fc7e60ecd982e55fbbcf3ae6cddcc4d6aaa681..0a3b50b6a13be5aa210073d2d01f614485bf6215 100644 --- a/jdk/src/java.base/share/classes/java/util/Formatter.java +++ b/jdk/src/java.base/share/classes/java/util/Formatter.java @@ -49,6 +49,7 @@ import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.Objects; import java.time.DateTimeException; import java.time.Instant; @@ -3860,7 +3861,7 @@ public final class Formatter implements Closeable, Flushable { ampm = dfs.getAmPmStrings(); } String s = ampm[t.get(Calendar.AM_PM)]; - sb.append(s.toLowerCase(l != null ? l : Locale.US)); + sb.append(s.toLowerCase(Objects.requireNonNullElse(l, Locale.US))); break; } case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?) @@ -3893,7 +3894,7 @@ public final class Formatter implements Closeable, Flushable { TimeZone tz = t.getTimeZone(); sb.append(tz.getDisplayName((t.get(Calendar.DST_OFFSET) != 0), TimeZone.SHORT, - (l == null) ? Locale.US : l)); + Objects.requireNonNullElse(l, Locale.US))); break; } @@ -3901,7 +3902,7 @@ public final class Formatter implements Closeable, Flushable { case DateTime.NAME_OF_DAY_ABBREV: // 'a' case DateTime.NAME_OF_DAY: { // 'A' int i = t.get(Calendar.DAY_OF_WEEK); - Locale lt = ((l == null) ? Locale.US : l); + Locale lt = Objects.requireNonNullElse(l, Locale.US); DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); if (c == DateTime.NAME_OF_DAY) sb.append(dfs.getWeekdays()[i]); @@ -3913,7 +3914,7 @@ public final class Formatter implements Closeable, Flushable { case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b case DateTime.NAME_OF_MONTH: { // 'B' int i = t.get(Calendar.MONTH); - Locale lt = ((l == null) ? Locale.US : l); + Locale lt = Objects.requireNonNullElse(l, Locale.US); DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); if (c == DateTime.NAME_OF_MONTH) sb.append(dfs.getMonths()[i]); @@ -3984,7 +3985,7 @@ public final class Formatter implements Closeable, Flushable { StringBuilder tsb = new StringBuilder(); print(tsb, t, DateTime.AM_PM, l); - sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US)); + sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, Locale.US))); break; } case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999) @@ -4092,7 +4093,7 @@ public final class Formatter implements Closeable, Flushable { ampm = dfs.getAmPmStrings(); } String s = ampm[t.get(ChronoField.AMPM_OF_DAY)]; - sb.append(s.toLowerCase(l != null ? l : Locale.US)); + sb.append(s.toLowerCase(Objects.requireNonNullElse(l, Locale.US))); break; } case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?) @@ -4131,7 +4132,7 @@ public final class Formatter implements Closeable, Flushable { sb.append(TimeZone.getTimeZone(zid.getId()) .getDisplayName(zid.getRules().isDaylightSavings(instant), TimeZone.SHORT, - (l == null) ? Locale.US : l)); + Objects.requireNonNullElse(l, Locale.US))); break; } sb.append(zid.getId()); @@ -4141,7 +4142,7 @@ public final class Formatter implements Closeable, Flushable { case DateTime.NAME_OF_DAY_ABBREV: // 'a' case DateTime.NAME_OF_DAY: { // 'A' int i = t.get(ChronoField.DAY_OF_WEEK) % 7 + 1; - Locale lt = ((l == null) ? Locale.US : l); + Locale lt = Objects.requireNonNullElse(l, Locale.US); DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); if (c == DateTime.NAME_OF_DAY) sb.append(dfs.getWeekdays()[i]); @@ -4153,7 +4154,7 @@ public final class Formatter implements Closeable, Flushable { case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b case DateTime.NAME_OF_MONTH: { // 'B' int i = t.get(ChronoField.MONTH_OF_YEAR) - 1; - Locale lt = ((l == null) ? Locale.US : l); + Locale lt = Objects.requireNonNullElse(l, Locale.US); DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); if (c == DateTime.NAME_OF_MONTH) sb.append(dfs.getMonths()[i]); @@ -4223,7 +4224,7 @@ public final class Formatter implements Closeable, Flushable { // this may be in wrong place for some locales StringBuilder tsb = new StringBuilder(); print(tsb, t, DateTime.AM_PM, l); - sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US)); + sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, Locale.US))); break; } case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999) diff --git a/jdk/src/java.base/share/classes/java/util/Objects.java b/jdk/src/java.base/share/classes/java/util/Objects.java index 65089553b87fb8b47a1305ef7d4acb164866baaa..4bd77d7c2656d29d7f4ae8bd19a1e2d84efb848d 100644 --- a/jdk/src/java.base/share/classes/java/util/Objects.java +++ b/jdk/src/java.base/share/classes/java/util/Objects.java @@ -295,7 +295,7 @@ public final class Objects { * {@code defaultObj} is {@code null} * @since 9 */ - public static <T> T nonNullElse(T obj, T defaultObj) { + public static <T> T requireNonNullElse(T obj, T defaultObj) { return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj"); } @@ -314,8 +314,9 @@ public final class Objects { * the {@code supplier.get()} value is {@code null} * @since 9 */ - public static <T> T nonNullElseGet(T obj, Supplier<? extends T> supplier) { - return (obj != null) ? obj : requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()"); + public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier) { + return (obj != null) ? obj + : requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()"); } /** diff --git a/jdk/src/java.base/share/classes/java/util/Random.java b/jdk/src/java.base/share/classes/java/util/Random.java index f22dca758f7a2e9677105e4e7af5f93c554d9be3..78e4953bfe89fcd69d0980358edf89d56bdc926c 100644 --- a/jdk/src/java.base/share/classes/java/util/Random.java +++ b/jdk/src/java.base/share/classes/java/util/Random.java @@ -34,7 +34,7 @@ import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.StreamSupport; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * An instance of this class is used to generate a stream of diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java index ee553e8f26145a345361634dfaa657321912bc09..45389ac9109e7f31da7d1fc6557d4b40d0272432 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -2775,7 +2775,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long RESULT; private static final long STACK; private static final long NEXT; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index 4c1180dc11bb779f3b94414b6c81f9d478c0898f..b2c2d2aa701c94b4150311d26d365d512e1ecdb6 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -297,7 +297,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> * Table accesses require volatile/atomic reads, writes, and * CASes. Because there is no other way to arrange this without * adding further indirections, we use intrinsics - * (sun.misc.Unsafe) operations. + * (jdk.internal.misc.Unsafe) operations. * * We use the top (sign) bit of Node hash fields for control * purposes -- it is available anyway because of addressing @@ -3287,7 +3287,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> return true; } - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long LOCKSTATE; static { try { @@ -6330,7 +6330,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long SIZECTL; private static final long TRANSFERINDEX; private static final long BASECOUNT; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java index 0991efc9e284f99b52ff0628e1c8e762c32a7c87..4f8fdd92c49084666ad7c2156aa74e589375e140 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -326,7 +326,7 @@ public class ConcurrentLinkedDeque<E> // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long PREV; private static final long ITEM; private static final long NEXT; @@ -1608,7 +1608,7 @@ public class ConcurrentLinkedDeque<E> // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long HEAD; private static final long TAIL; static { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index 6e68ed0d3331ccd5d3446c7ca5d0565ae387b66e..d302b6f55b88f66366216779f3700cffe2134bdd 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -929,7 +929,7 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long HEAD; private static final long TAIL; private static final long ITEM; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index 60d3c42e8bbe4b98bfc4551e624e8c790d5589fe..745de306bc1523f820fa587d5707f035d3e9edc2 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -534,7 +534,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V> // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long VALUE; private static final long NEXT; @@ -614,7 +614,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V> } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long RIGHT; static { try { @@ -3596,7 +3596,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V> } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long HEAD; static { try { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java index 96dff4f898959634b771b36f7680650dd92e2289..2ecacf8e18515ac3e3e3eee912a5a67404269d62 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -510,7 +510,7 @@ public class ConcurrentSkipListSet<E> U.putObjectVolatile(this, MAP, map); } - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long MAP; static { try { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index 771d8b44fa9c40c11a564492b8b45adbd1a0a4eb..65baf7c87c80056d31319440ef3f2c68dbd088ec 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -1545,7 +1545,7 @@ public class CopyOnWriteArrayList<E> private void resetLock() { U.putObjectVolatile(this, LOCK, new Object()); } - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long LOCK; static { try { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java index eebc700f93292c9ceaac5d870d0e99547e872c77..24c154e2f055885f67fb849800d0fd238a542152 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java @@ -754,7 +754,7 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> { protected void setRawResult(T t) { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long PENDING; static { try { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java index 4c03c25d03d392198850a3fdaea59ac19c97b05f..503d2500578b1d64f9459ebbc646e3c5b56eafd6 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java @@ -625,7 +625,7 @@ public class Exchanger<V> { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long BOUND; private static final long SLOT; private static final long MATCH; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index d2490854abf3fb429a081c6a94b51c16a5800480..e4e91a1a187cbc1a8a3da8b2a806bd929babc8fc 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -1337,7 +1337,7 @@ public class ForkJoinPool extends AbstractExecutorService { } // Unsafe mechanics. Note that some are (and must be) the same as in FJP - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long QLOCK; private static final int ABASE; private static final int ASHIFT; @@ -3452,7 +3452,7 @@ public class ForkJoinPool extends AbstractExecutorService { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long CTL; private static final long RUNSTATE; private static final int ABASE; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java index 6a373367d0e2feba5fde94b2c2126d1151ba2561..2b714dff9b42bc5f9274dceb44821b04c4fa29fc 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java @@ -1517,7 +1517,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long STATUS; static { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java index e98ba993c308aa54e75baf4c27d9e02106fb4efe..54d8931de4f5780de1d6864fc1b13b3d7d654b9c 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java @@ -185,7 +185,7 @@ public class ForkJoinWorkerThread extends Thread { } // Set up to allow setting thread fields in constructor - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long THREADLOCALS; private static final long INHERITABLETHREADLOCALS; private static final long INHERITEDACCESSCONTROLCONTEXT; @@ -248,7 +248,7 @@ public class ForkJoinWorkerThread extends Thread { */ private static ThreadGroup createThreadGroup() { try { - sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe(); + jdk.internal.misc.Unsafe u = jdk.internal.misc.Unsafe.getUnsafe(); long tg = u.objectFieldOffset (Thread.class.getDeclaredField("group")); long gp = u.objectFieldOffset diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java index 62c2bfcb291fa97e4c8ae2b85154646ac6a366f2..27943fd7cb6549f2689d70426850d09414eaec36 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java @@ -484,7 +484,7 @@ public class FutureTask<V> implements RunnableFuture<V> { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long STATE; private static final long RUNNER; private static final long WAITERS; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java index 8127fe3a34fe1cfe629cd12a669c13fa093d4001..02ffd871b7a3357c57fcdadec39fc0e8a7cda654 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -538,7 +538,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E> private static final long serialVersionUID = -3375979862319811754L; // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long ITEM; private static final long NEXT; private static final long WAITER; @@ -1564,7 +1564,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E> // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long HEAD; private static final long TAIL; private static final long SWEEPVOTES; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java index 9ef99361f45d219ed5186af349e9f9bd281655e6..e8d91e557c072b3e0d716d2e4a52c7ed096cfb61 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java @@ -1137,7 +1137,7 @@ public class Phaser { // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long STATE; static { try { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java index 7432529305ec4581c9258a4f00b7bc8289da91d4..652fd6958cfe658142b3c8d6e04340b104f77a44 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -1010,7 +1010,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long ALLOCATIONSPINLOCK; static { try { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java index 0d6e66bf51669a24c2f5ff7e8ed5126c569b96aa..03462ac1ef478033e3f5f0407c039bfcd48759e0 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java @@ -1596,7 +1596,7 @@ public class SubmissionPublisher<T> implements Flow.Publisher<T>, } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long CTL; private static final long TAIL; private static final long HEAD; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java index 029aa9c895cb64489104c23f694c0623956f83c3..069d0a6b85199c849ecbbb0d0743cb635aae7a12 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java @@ -283,7 +283,7 @@ public class SynchronousQueue<E> extends AbstractQueue<E> } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long MATCH; private static final long NEXT; @@ -509,7 +509,7 @@ public class SynchronousQueue<E> extends AbstractQueue<E> } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long HEAD; static { try { @@ -575,7 +575,7 @@ public class SynchronousQueue<E> extends AbstractQueue<E> } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long ITEM; private static final long NEXT; @@ -817,7 +817,7 @@ public class SynchronousQueue<E> extends AbstractQueue<E> } } - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long HEAD; private static final long TAIL; private static final long CLEANME; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index f9542d504d76a881da1507940d8fda8df01d16ad..f4bf5a4fef2adc26013d303ddc291750872b0dbf 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -1050,7 +1050,7 @@ public class ThreadLocalRandom extends Random { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long SEED; private static final long PROBE; private static final long SECONDARY; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java index b2a23903c22ac6037402090f12fa81681cbf36c0..01fc1c2c0d71a5aa1d79943d94fa0478468a84c4 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java @@ -49,7 +49,7 @@ package java.util.concurrent.atomic; public class AtomicBoolean implements java.io.Serializable { private static final long serialVersionUID = 4654671469794556979L; - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long VALUE; static { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java index 19b341819b9fa904c49992549bea351fc2c51192..96e13f60ed8197e1663fb38ee7662c8fb5df3917 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java @@ -54,7 +54,7 @@ import java.util.function.IntUnaryOperator; public class AtomicInteger extends Number implements java.io.Serializable { private static final long serialVersionUID = 6214790243416807050L; - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long VALUE; static { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java index 2ea9a2720087038538e1f3a416684d129adc7c20..f3a262b65b42f0923f3b1cb59b9d597041a44e33 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java @@ -49,7 +49,7 @@ import java.util.function.IntUnaryOperator; public class AtomicIntegerArray implements java.io.Serializable { private static final long serialVersionUID = 2862133569453604235L; - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final int ABASE; private static final int ASHIFT; private final int[] array; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java index 06e517d1a2bb1153056a88236125b1bfce512bc3..1ec99ccc42fe7c95b305c8f1eea434a8d05c0324 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java @@ -367,7 +367,7 @@ public abstract class AtomicIntegerFieldUpdater<T> { */ private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> { - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private final long offset; private final Class<T> tclass; private final Class<?> cclass; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java index b919f1e3c7a20dc8ed3a38771a791331d4b05fa6..2af5d1dd07f2350b8ccf93099a3d7151ec26a50d 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java @@ -54,7 +54,7 @@ import java.util.function.LongUnaryOperator; public class AtomicLong extends Number implements java.io.Serializable { private static final long serialVersionUID = 1927816293512124184L; - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long VALUE; /** diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java index d1af039aa617487749ca15f82d435243dea6002e..58aa1875b197eea00526f2c04005613d646765d1 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java @@ -48,7 +48,7 @@ import java.util.function.LongUnaryOperator; public class AtomicLongArray implements java.io.Serializable { private static final long serialVersionUID = -2308431214976778248L; - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final int ABASE; private static final int ASHIFT; private final long[] array; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java index 5cb20197126a12b705354ef70c54fd18456cc293..870a311aebf418e754d28da273b4c6fdca8b9690 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java @@ -366,7 +366,7 @@ public abstract class AtomicLongFieldUpdater<T> { } private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> { - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private final long offset; private final Class<T> tclass; private final Class<?> cclass; @@ -490,7 +490,7 @@ public abstract class AtomicLongFieldUpdater<T> { private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> { - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private final long offset; private final Class<T> tclass; private final Class<?> cclass; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java index b49118b1c6043e0c3fd8b62dfc4b8b80253b3a77..8204c3fcc612a4e828731538f60c45238910cc7c 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java @@ -190,7 +190,7 @@ public class AtomicMarkableReference<V> { // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long PAIR; static { try { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java index dbc668582f77184da68cddcb36971cfb83ab3736..9d4d2a385c7e27c0ddc58b6cf3c12fe37ec6a0b7 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java @@ -49,7 +49,7 @@ import java.util.function.UnaryOperator; public class AtomicReference<V> implements java.io.Serializable { private static final long serialVersionUID = -1848883965231344442L; - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long VALUE; static { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index cce148e6f0e6b1fd3e425cd6adfa630a5574306b..03f950d43e0561b661bf8e235746badd3188d607 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -52,7 +52,7 @@ import java.util.function.UnaryOperator; public class AtomicReferenceArray<E> implements java.io.Serializable { private static final long serialVersionUID = -6209656149925076980L; - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long ARRAY; private static final int ABASE; private static final int ASHIFT; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index f33498c8f9f0cafbb3e17f9b053c5e7576df72fd..aa89aead91b9b4c7c54ad35df7ecf318c6ddc05a 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -284,7 +284,7 @@ public abstract class AtomicReferenceFieldUpdater<T,V> { private static final class AtomicReferenceFieldUpdaterImpl<T,V> extends AtomicReferenceFieldUpdater<T,V> { - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private final long offset; private final Class<T> tclass; private final Class<V> vclass; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java index 40ceeb2650f97d168c45772e0195ecccc0545f64..fd520d7d889d8bb5384de76189623e4624b09b89 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java @@ -190,7 +190,7 @@ public class AtomicStampedReference<V> { // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long PAIR; static { try { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java index 18d720fa391c096e9df9c008b5b6f0345fc98bcb..153a3adc3781910d7ce9f582ed0f12a1313ede6a 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java @@ -133,7 +133,7 @@ abstract class Striped64 extends Number { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long VALUE; static { try { @@ -372,7 +372,7 @@ abstract class Striped64 extends Number { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long BASE; private static final long CELLSBUSY; private static final long PROBE; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java index 7f6de8971ceb5fcb971545fa2222f422720cb795..06f50846234168d61542cadd53e212856eb8e317 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java @@ -1821,7 +1821,7 @@ public abstract class AbstractQueuedLongSynchronizer * are at it, we do the same for other CASable fields (which could * otherwise be done with atomic field updaters). */ - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long STATE; private static final long HEAD; private static final long TAIL; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java index 1f36435bb4cd0421e9d81ad3c991c96457894a9a..3d604a632147ed4bda20da86b726e40031ca11e6 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java @@ -524,7 +524,7 @@ public abstract class AbstractQueuedSynchronizer return U.compareAndSwapObject(this, NEXT, expect, update); } - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long NEXT; static final long PREV; private static final long THREAD; @@ -2285,7 +2285,7 @@ public abstract class AbstractQueuedSynchronizer * are at it, we do the same for other CASable fields (which could * otherwise be done with atomic field updaters). */ - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long STATE; private static final long HEAD; private static final long TAIL; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java index 297de583436d1475a3c09c68c91dacff2a15a33c..a82d2d9f736624c3ae878cf6f070792da3d69732 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java @@ -394,7 +394,7 @@ public class LockSupport { } // Hotspot implementation via intrinsics API - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long PARKBLOCKER; private static final long SECONDARY; static { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java index c41b4285a6715314c62dc50e430fdc92f3492d36..a2c627aed3ba7e1bd412129774be8cec6d1c3b2d 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java @@ -1501,7 +1501,7 @@ public class ReentrantReadWriteLock } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long TID; static { try { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java index d6895996d914135bd21b6bd606fb4cecc5985c91..0e8252587b57993ef8d12dcbb2f809bda43435f9 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java @@ -1398,7 +1398,7 @@ public class StampedLock implements java.io.Serializable { } // Unsafe mechanics - private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long STATE; private static final long WHEAD; private static final long WTAIL; diff --git a/jdk/src/java.base/share/classes/java/util/zip/CRC32C.java b/jdk/src/java.base/share/classes/java/util/zip/CRC32C.java index c40886fafa61bdcd9279055cc0f98f54ac8dc3e2..2d82625780e05fcdfb0346ebb812274f3e7dc448 100644 --- a/jdk/src/java.base/share/classes/java/util/zip/CRC32C.java +++ b/jdk/src/java.base/share/classes/java/util/zip/CRC32C.java @@ -28,7 +28,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import jdk.internal.HotSpotIntrinsicCandidate; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.nio.ch.DirectBuffer; /** diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java index 39bbbc625a1bb78c86392861401d102a45bd62a6..1d74a0da741abf580a9f428fefc6fc2f1f00e8f2 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java @@ -30,7 +30,7 @@ import java.io.Console; import java.io.FileDescriptor; import java.security.ProtectionDomain; import java.security.AccessController; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** A repository of "shared secrets", which are a mechanism for calling implementation-private methods in another package without diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java new file mode 100644 index 0000000000000000000000000000000000000000..83bb4f34ff11b2c306110c21f72e93974e5104b5 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -0,0 +1,1391 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.misc; + +import java.lang.reflect.Field; +import java.security.ProtectionDomain; + +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; +import sun.misc.VM; + +import jdk.internal.HotSpotIntrinsicCandidate; + + +/** + * A collection of methods for performing low-level, unsafe operations. + * Although the class and all methods are public, use of this class is + * limited because only trusted code can obtain instances of it. + * + * @author John R. Rose + * @see #getUnsafe + */ + +public final class Unsafe { + + private static native void registerNatives(); + static { + registerNatives(); + sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe"); + } + + private Unsafe() {} + + private static final Unsafe theUnsafe = new Unsafe(); + + /** + * Provides the caller with the capability of performing unsafe + * operations. + * + * <p>The returned {@code Unsafe} object should be carefully guarded + * by the caller, since it can be used to read and write data at arbitrary + * memory addresses. It must never be passed to untrusted code. + * + * <p>Most methods in this class are very low-level, and correspond to a + * small number of hardware instructions (on typical machines). Compilers + * are encouraged to optimize these methods accordingly. + * + * <p>Here is a suggested idiom for using unsafe operations: + * + * <pre> {@code + * class MyTrustedClass { + * private static final Unsafe unsafe = Unsafe.getUnsafe(); + * ... + * private long myCountAddress = ...; + * public int getCount() { return unsafe.getByte(myCountAddress); } + * }}</pre> + * + * (It may assist compilers to make the local variable {@code final}.) + * + * @throws SecurityException if a security manager exists and its + * {@code checkPropertiesAccess} method doesn't allow + * access to the system properties. + */ + @CallerSensitive + public static Unsafe getUnsafe() { + Class<?> caller = Reflection.getCallerClass(); + if (!VM.isSystemDomainLoader(caller.getClassLoader())) + throw new SecurityException("Unsafe"); + return theUnsafe; + } + + /// peek and poke operations + /// (compilers should optimize these to memory ops) + + // These work on object fields in the Java heap. + // They will not work on elements of packed arrays. + + /** + * Fetches a value from a given Java variable. + * More specifically, fetches a field or array element within the given + * object {@code o} at the given offset, or (if {@code o} is null) + * from the memory address whose numerical value is the given offset. + * <p> + * The results are undefined unless one of the following cases is true: + * <ul> + * <li>The offset was obtained from {@link #objectFieldOffset} on + * the {@link java.lang.reflect.Field} of some Java field and the object + * referred to by {@code o} is of a class compatible with that + * field's class. + * + * <li>The offset and object reference {@code o} (either null or + * non-null) were both obtained via {@link #staticFieldOffset} + * and {@link #staticFieldBase} (respectively) from the + * reflective {@link Field} representation of some Java field. + * + * <li>The object referred to by {@code o} is an array, and the offset + * is an integer of the form {@code B+N*S}, where {@code N} is + * a valid index into the array, and {@code B} and {@code S} are + * the values obtained by {@link #arrayBaseOffset} and {@link + * #arrayIndexScale} (respectively) from the array's class. The value + * referred to is the {@code N}<em>th</em> element of the array. + * + * </ul> + * <p> + * If one of the above cases is true, the call references a specific Java + * variable (field or array element). However, the results are undefined + * if that variable is not in fact of the type returned by this method. + * <p> + * This method refers to a variable by means of two parameters, and so + * it provides (in effect) a <em>double-register</em> addressing mode + * for Java variables. When the object reference is null, this method + * uses its offset as an absolute address. This is similar in operation + * to methods such as {@link #getInt(long)}, which provide (in effect) a + * <em>single-register</em> addressing mode for non-Java variables. + * However, because Java variables may have a different layout in memory + * from non-Java variables, programmers should not assume that these + * two addressing modes are ever equivalent. Also, programmers should + * remember that offsets from the double-register addressing mode cannot + * be portably confused with longs used in the single-register addressing + * mode. + * + * @param o Java heap object in which the variable resides, if any, else + * null + * @param offset indication of where the variable resides in a Java heap + * object, if any, else a memory address locating the variable + * statically + * @return the value fetched from the indicated Java variable + * @throws RuntimeException No defined exceptions are thrown, not even + * {@link NullPointerException} + */ + @HotSpotIntrinsicCandidate + public native int getInt(Object o, long offset); + + /** + * Stores a value into a given Java variable. + * <p> + * The first two parameters are interpreted exactly as with + * {@link #getInt(Object, long)} to refer to a specific + * Java variable (field or array element). The given value + * is stored into that variable. + * <p> + * The variable must be of the same type as the method + * parameter {@code x}. + * + * @param o Java heap object in which the variable resides, if any, else + * null + * @param offset indication of where the variable resides in a Java heap + * object, if any, else a memory address locating the variable + * statically + * @param x the value to store into the indicated Java variable + * @throws RuntimeException No defined exceptions are thrown, not even + * {@link NullPointerException} + */ + @HotSpotIntrinsicCandidate + public native void putInt(Object o, long offset, int x); + + /** + * Fetches a reference value from a given Java variable. + * @see #getInt(Object, long) + */ + @HotSpotIntrinsicCandidate + public native Object getObject(Object o, long offset); + + /** + * Stores a reference value into a given Java variable. + * <p> + * Unless the reference {@code x} being stored is either null + * or matches the field type, the results are undefined. + * If the reference {@code o} is non-null, card marks or + * other store barriers for that object (if the VM requires them) + * are updated. + * @see #putInt(Object, long, int) + */ + @HotSpotIntrinsicCandidate + public native void putObject(Object o, long offset, Object x); + + /** @see #getInt(Object, long) */ + @HotSpotIntrinsicCandidate + public native boolean getBoolean(Object o, long offset); + /** @see #putInt(Object, long, int) */ + @HotSpotIntrinsicCandidate + public native void putBoolean(Object o, long offset, boolean x); + /** @see #getInt(Object, long) */ + @HotSpotIntrinsicCandidate + public native byte getByte(Object o, long offset); + /** @see #putInt(Object, long, int) */ + @HotSpotIntrinsicCandidate + public native void putByte(Object o, long offset, byte x); + /** @see #getInt(Object, long) */ + @HotSpotIntrinsicCandidate + public native short getShort(Object o, long offset); + /** @see #putInt(Object, long, int) */ + @HotSpotIntrinsicCandidate + public native void putShort(Object o, long offset, short x); + /** @see #getInt(Object, long) */ + @HotSpotIntrinsicCandidate + public native char getChar(Object o, long offset); + /** @see #putInt(Object, long, int) */ + @HotSpotIntrinsicCandidate + public native void putChar(Object o, long offset, char x); + /** @see #getInt(Object, long) */ + @HotSpotIntrinsicCandidate + public native long getLong(Object o, long offset); + /** @see #putInt(Object, long, int) */ + @HotSpotIntrinsicCandidate + public native void putLong(Object o, long offset, long x); + /** @see #getInt(Object, long) */ + @HotSpotIntrinsicCandidate + public native float getFloat(Object o, long offset); + /** @see #putInt(Object, long, int) */ + @HotSpotIntrinsicCandidate + public native void putFloat(Object o, long offset, float x); + /** @see #getInt(Object, long) */ + @HotSpotIntrinsicCandidate + public native double getDouble(Object o, long offset); + /** @see #putInt(Object, long, int) */ + @HotSpotIntrinsicCandidate + public native void putDouble(Object o, long offset, double x); + + // These read VM internal data. + + /** + * Fetches an uncompressed reference value from a given native variable + * ignoring the VM's compressed references mode. + * + * @param address a memory address locating the variable + * @return the value fetched from the indicated native variable + */ + public native Object getUncompressedObject(long address); + + /** + * Fetches the {@link java.lang.Class} Java mirror for the given native + * metaspace {@code Klass} pointer. + * + * @param metaspaceKlass a native metaspace {@code Klass} pointer + * @return the {@link java.lang.Class} Java mirror + */ + public native Class<?> getJavaMirror(long metaspaceKlass); + + /** + * Fetches a native metaspace {@code Klass} pointer for the given Java + * object. + * + * @param o Java heap object for which to fetch the class pointer + * @return a native metaspace {@code Klass} pointer + */ + public native long getKlassPointer(Object o); + + // These work on values in the C heap. + + /** + * Fetches a value from a given memory address. If the address is zero, or + * does not point into a block obtained from {@link #allocateMemory}, the + * results are undefined. + * + * @see #allocateMemory + */ + @HotSpotIntrinsicCandidate + public native byte getByte(long address); + + /** + * Stores a value into a given memory address. If the address is zero, or + * does not point into a block obtained from {@link #allocateMemory}, the + * results are undefined. + * + * @see #getByte(long) + */ + @HotSpotIntrinsicCandidate + public native void putByte(long address, byte x); + + /** @see #getByte(long) */ + @HotSpotIntrinsicCandidate + public native short getShort(long address); + /** @see #putByte(long, byte) */ + @HotSpotIntrinsicCandidate + public native void putShort(long address, short x); + /** @see #getByte(long) */ + @HotSpotIntrinsicCandidate + public native char getChar(long address); + /** @see #putByte(long, byte) */ + @HotSpotIntrinsicCandidate + public native void putChar(long address, char x); + /** @see #getByte(long) */ + @HotSpotIntrinsicCandidate + public native int getInt(long address); + /** @see #putByte(long, byte) */ + @HotSpotIntrinsicCandidate + public native void putInt(long address, int x); + /** @see #getByte(long) */ + @HotSpotIntrinsicCandidate + public native long getLong(long address); + /** @see #putByte(long, byte) */ + @HotSpotIntrinsicCandidate + public native void putLong(long address, long x); + /** @see #getByte(long) */ + @HotSpotIntrinsicCandidate + public native float getFloat(long address); + /** @see #putByte(long, byte) */ + @HotSpotIntrinsicCandidate + public native void putFloat(long address, float x); + /** @see #getByte(long) */ + @HotSpotIntrinsicCandidate + public native double getDouble(long address); + /** @see #putByte(long, byte) */ + @HotSpotIntrinsicCandidate + public native void putDouble(long address, double x); + + /** + * Fetches a native pointer from a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + * <p>If the native pointer is less than 64 bits wide, it is extended as + * an unsigned number to a Java long. The pointer may be indexed by any + * given byte offset, simply by adding that offset (as a simple integer) to + * the long representing the pointer. The number of bytes actually read + * from the target address may be determined by consulting {@link + * #addressSize}. + * + * @see #allocateMemory + */ + @HotSpotIntrinsicCandidate + public native long getAddress(long address); + + /** + * Stores a native pointer into a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + * <p>The number of bytes actually written at the target address may be + * determined by consulting {@link #addressSize}. + * + * @see #getAddress(long) + */ + @HotSpotIntrinsicCandidate + public native void putAddress(long address, long x); + + /// wrappers for malloc, realloc, free: + + /** + * Allocates a new block of native memory, of the given size in bytes. The + * contents of the memory are uninitialized; they will generally be + * garbage. The resulting native pointer will never be zero, and will be + * aligned for all value types. Dispose of this memory by calling {@link + * #freeMemory}, or resize it with {@link #reallocateMemory}. + * + * @throws IllegalArgumentException if the size is negative or too large + * for the native size_t type + * + * @throws OutOfMemoryError if the allocation is refused by the system + * + * @see #getByte(long) + * @see #putByte(long, byte) + */ + public native long allocateMemory(long bytes); + + /** + * Resizes a new block of native memory, to the given size in bytes. The + * contents of the new block past the size of the old block are + * uninitialized; they will generally be garbage. The resulting native + * pointer will be zero if and only if the requested size is zero. The + * resulting native pointer will be aligned for all value types. Dispose + * of this memory by calling {@link #freeMemory}, or resize it with {@link + * #reallocateMemory}. The address passed to this method may be null, in + * which case an allocation will be performed. + * + * @throws IllegalArgumentException if the size is negative or too large + * for the native size_t type + * + * @throws OutOfMemoryError if the allocation is refused by the system + * + * @see #allocateMemory + */ + public native long reallocateMemory(long address, long bytes); + + /** + * Sets all bytes in a given block of memory to a fixed value + * (usually zero). + * + * <p>This method determines a block's base address by means of two parameters, + * and so it provides (in effect) a <em>double-register</em> addressing mode, + * as discussed in {@link #getInt(Object,long)}. When the object reference is null, + * the offset supplies an absolute base address. + * + * <p>The stores are in coherent (atomic) units of a size determined + * by the address and length parameters. If the effective address and + * length are all even modulo 8, the stores take place in 'long' units. + * If the effective address and length are (resp.) even modulo 4 or 2, + * the stores take place in units of 'int' or 'short'. + * + * @since 1.7 + */ + public native void setMemory(Object o, long offset, long bytes, byte value); + + /** + * Sets all bytes in a given block of memory to a fixed value + * (usually zero). This provides a <em>single-register</em> addressing mode, + * as discussed in {@link #getInt(Object,long)}. + * + * <p>Equivalent to {@code setMemory(null, address, bytes, value)}. + */ + public void setMemory(long address, long bytes, byte value) { + setMemory(null, address, bytes, value); + } + + /** + * Sets all bytes in a given block of memory to a copy of another + * block. + * + * <p>This method determines each block's base address by means of two parameters, + * and so it provides (in effect) a <em>double-register</em> addressing mode, + * as discussed in {@link #getInt(Object,long)}. When the object reference is null, + * the offset supplies an absolute base address. + * + * <p>The transfers are in coherent (atomic) units of a size determined + * by the address and length parameters. If the effective addresses and + * length are all even modulo 8, the transfer takes place in 'long' units. + * If the effective addresses and length are (resp.) even modulo 4 or 2, + * the transfer takes place in units of 'int' or 'short'. + * + * @since 1.7 + */ + @HotSpotIntrinsicCandidate + public native void copyMemory(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes); + /** + * Sets all bytes in a given block of memory to a copy of another + * block. This provides a <em>single-register</em> addressing mode, + * as discussed in {@link #getInt(Object,long)}. + * + * Equivalent to {@code copyMemory(null, srcAddress, null, destAddress, bytes)}. + */ + public void copyMemory(long srcAddress, long destAddress, long bytes) { + copyMemory(null, srcAddress, null, destAddress, bytes); + } + + /** + * Disposes of a block of native memory, as obtained from {@link + * #allocateMemory} or {@link #reallocateMemory}. The address passed to + * this method may be null, in which case no action is taken. + * + * @see #allocateMemory + */ + public native void freeMemory(long address); + + /// random queries + + /** + * This constant differs from all results that will ever be returned from + * {@link #staticFieldOffset}, {@link #objectFieldOffset}, + * or {@link #arrayBaseOffset}. + */ + public static final int INVALID_FIELD_OFFSET = -1; + + /** + * Reports the location of a given field in the storage allocation of its + * class. Do not expect to perform any sort of arithmetic on this offset; + * it is just a cookie which is passed to the unsafe heap memory accessors. + * + * <p>Any given field will always have the same offset and base, and no + * two distinct fields of the same class will ever have the same offset + * and base. + * + * <p>As of 1.4.1, offsets for fields are represented as long values, + * although the Sun JVM does not use the most significant 32 bits. + * However, JVM implementations which store static fields at absolute + * addresses can use long offsets and null base pointers to express + * the field locations in a form usable by {@link #getInt(Object,long)}. + * Therefore, code which will be ported to such JVMs on 64-bit platforms + * must preserve all bits of static field offsets. + * @see #getInt(Object, long) + */ + public native long objectFieldOffset(Field f); + + /** + * Reports the location of a given static field, in conjunction with {@link + * #staticFieldBase}. + * <p>Do not expect to perform any sort of arithmetic on this offset; + * it is just a cookie which is passed to the unsafe heap memory accessors. + * + * <p>Any given field will always have the same offset, and no two distinct + * fields of the same class will ever have the same offset. + * + * <p>As of 1.4.1, offsets for fields are represented as long values, + * although the Sun JVM does not use the most significant 32 bits. + * It is hard to imagine a JVM technology which needs more than + * a few bits to encode an offset within a non-array object, + * However, for consistency with other methods in this class, + * this method reports its result as a long value. + * @see #getInt(Object, long) + */ + public native long staticFieldOffset(Field f); + + /** + * Reports the location of a given static field, in conjunction with {@link + * #staticFieldOffset}. + * <p>Fetch the base "Object", if any, with which static fields of the + * given class can be accessed via methods like {@link #getInt(Object, + * long)}. This value may be null. This value may refer to an object + * which is a "cookie", not guaranteed to be a real Object, and it should + * not be used in any way except as argument to the get and put routines in + * this class. + */ + public native Object staticFieldBase(Field f); + + /** + * Detects if the given class may need to be initialized. This is often + * needed in conjunction with obtaining the static field base of a + * class. + * @return false only if a call to {@code ensureClassInitialized} would have no effect + */ + public native boolean shouldBeInitialized(Class<?> c); + + /** + * Ensures the given class has been initialized. This is often + * needed in conjunction with obtaining the static field base of a + * class. + */ + public native void ensureClassInitialized(Class<?> c); + + /** + * Reports the offset of the first element in the storage allocation of a + * given array class. If {@link #arrayIndexScale} returns a non-zero value + * for the same class, you may use that scale factor, together with this + * base offset, to form new offsets to access elements of arrays of the + * given class. + * + * @see #getInt(Object, long) + * @see #putInt(Object, long, int) + */ + public native int arrayBaseOffset(Class<?> arrayClass); + + /** The value of {@code arrayBaseOffset(boolean[].class)} */ + public static final int ARRAY_BOOLEAN_BASE_OFFSET + = theUnsafe.arrayBaseOffset(boolean[].class); + + /** The value of {@code arrayBaseOffset(byte[].class)} */ + public static final int ARRAY_BYTE_BASE_OFFSET + = theUnsafe.arrayBaseOffset(byte[].class); + + /** The value of {@code arrayBaseOffset(short[].class)} */ + public static final int ARRAY_SHORT_BASE_OFFSET + = theUnsafe.arrayBaseOffset(short[].class); + + /** The value of {@code arrayBaseOffset(char[].class)} */ + public static final int ARRAY_CHAR_BASE_OFFSET + = theUnsafe.arrayBaseOffset(char[].class); + + /** The value of {@code arrayBaseOffset(int[].class)} */ + public static final int ARRAY_INT_BASE_OFFSET + = theUnsafe.arrayBaseOffset(int[].class); + + /** The value of {@code arrayBaseOffset(long[].class)} */ + public static final int ARRAY_LONG_BASE_OFFSET + = theUnsafe.arrayBaseOffset(long[].class); + + /** The value of {@code arrayBaseOffset(float[].class)} */ + public static final int ARRAY_FLOAT_BASE_OFFSET + = theUnsafe.arrayBaseOffset(float[].class); + + /** The value of {@code arrayBaseOffset(double[].class)} */ + public static final int ARRAY_DOUBLE_BASE_OFFSET + = theUnsafe.arrayBaseOffset(double[].class); + + /** The value of {@code arrayBaseOffset(Object[].class)} */ + public static final int ARRAY_OBJECT_BASE_OFFSET + = theUnsafe.arrayBaseOffset(Object[].class); + + /** + * Reports the scale factor for addressing elements in the storage + * allocation of a given array class. However, arrays of "narrow" types + * will generally not work properly with accessors like {@link + * #getByte(Object, long)}, so the scale factor for such classes is reported + * as zero. + * + * @see #arrayBaseOffset + * @see #getInt(Object, long) + * @see #putInt(Object, long, int) + */ + public native int arrayIndexScale(Class<?> arrayClass); + + /** The value of {@code arrayIndexScale(boolean[].class)} */ + public static final int ARRAY_BOOLEAN_INDEX_SCALE + = theUnsafe.arrayIndexScale(boolean[].class); + + /** The value of {@code arrayIndexScale(byte[].class)} */ + public static final int ARRAY_BYTE_INDEX_SCALE + = theUnsafe.arrayIndexScale(byte[].class); + + /** The value of {@code arrayIndexScale(short[].class)} */ + public static final int ARRAY_SHORT_INDEX_SCALE + = theUnsafe.arrayIndexScale(short[].class); + + /** The value of {@code arrayIndexScale(char[].class)} */ + public static final int ARRAY_CHAR_INDEX_SCALE + = theUnsafe.arrayIndexScale(char[].class); + + /** The value of {@code arrayIndexScale(int[].class)} */ + public static final int ARRAY_INT_INDEX_SCALE + = theUnsafe.arrayIndexScale(int[].class); + + /** The value of {@code arrayIndexScale(long[].class)} */ + public static final int ARRAY_LONG_INDEX_SCALE + = theUnsafe.arrayIndexScale(long[].class); + + /** The value of {@code arrayIndexScale(float[].class)} */ + public static final int ARRAY_FLOAT_INDEX_SCALE + = theUnsafe.arrayIndexScale(float[].class); + + /** The value of {@code arrayIndexScale(double[].class)} */ + public static final int ARRAY_DOUBLE_INDEX_SCALE + = theUnsafe.arrayIndexScale(double[].class); + + /** The value of {@code arrayIndexScale(Object[].class)} */ + public static final int ARRAY_OBJECT_INDEX_SCALE + = theUnsafe.arrayIndexScale(Object[].class); + + /** + * Reports the size in bytes of a native pointer, as stored via {@link + * #putAddress}. This value will be either 4 or 8. Note that the sizes of + * other primitive types (as stored in native memory blocks) is determined + * fully by their information content. + */ + public native int addressSize(); + + /** The value of {@code addressSize()} */ + public static final int ADDRESS_SIZE = theUnsafe.addressSize(); + + /** + * Reports the size in bytes of a native memory page (whatever that is). + * This value will always be a power of two. + */ + public native int pageSize(); + + + /// random trusted operations from JNI: + + /** + * Tells the VM to define a class, without security checks. By default, the + * class loader and protection domain come from the caller's class. + */ + public native Class<?> defineClass(String name, byte[] b, int off, int len, + ClassLoader loader, + ProtectionDomain protectionDomain); + + /** + * Defines a class but does not make it known to the class loader or system dictionary. + * <p> + * For each CP entry, the corresponding CP patch must either be null or have + * the a format that matches its tag: + * <ul> + * <li>Integer, Long, Float, Double: the corresponding wrapper object type from java.lang + * <li>Utf8: a string (must have suitable syntax if used as signature or name) + * <li>Class: any java.lang.Class object + * <li>String: any object (not just a java.lang.String) + * <li>InterfaceMethodRef: (NYI) a method handle to invoke on that call site's arguments + * </ul> + * @param hostClass context for linkage, access control, protection domain, and class loader + * @param data bytes of a class file + * @param cpPatches where non-null entries exist, they replace corresponding CP entries in data + */ + public native Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches); + + /** + * Allocates an instance but does not run any constructor. + * Initializes the class if it has not yet been. + */ + @HotSpotIntrinsicCandidate + public native Object allocateInstance(Class<?> cls) + throws InstantiationException; + + /** Throws the exception without telling the verifier. */ + public native void throwException(Throwable ee); + + /** + * Atomically updates Java variable to {@code x} if it is currently + * holding {@code expected}. + * + * <p>This operation has memory semantics of a {@code volatile} read + * and write. Corresponds to C11 atomic_compare_exchange_strong. + * + * @return {@code true} if successful + */ + @HotSpotIntrinsicCandidate + public final native boolean compareAndSwapObject(Object o, long offset, + Object expected, + Object x); + + /** + * Atomically updates Java variable to {@code x} if it is currently + * holding {@code expected}. + * + * <p>This operation has memory semantics of a {@code volatile} read + * and write. Corresponds to C11 atomic_compare_exchange_strong. + * + * @return {@code true} if successful + */ + @HotSpotIntrinsicCandidate + public final native boolean compareAndSwapInt(Object o, long offset, + int expected, + int x); + + /** + * Atomically updates Java variable to {@code x} if it is currently + * holding {@code expected}. + * + * <p>This operation has memory semantics of a {@code volatile} read + * and write. Corresponds to C11 atomic_compare_exchange_strong. + * + * @return {@code true} if successful + */ + @HotSpotIntrinsicCandidate + public final native boolean compareAndSwapLong(Object o, long offset, + long expected, + long x); + + /** + * Fetches a reference value from a given Java variable, with volatile + * load semantics. Otherwise identical to {@link #getObject(Object, long)} + */ + @HotSpotIntrinsicCandidate + public native Object getObjectVolatile(Object o, long offset); + + /** + * Stores a reference value into a given Java variable, with + * volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)} + */ + @HotSpotIntrinsicCandidate + public native void putObjectVolatile(Object o, long offset, Object x); + + /** Volatile version of {@link #getInt(Object, long)} */ + @HotSpotIntrinsicCandidate + public native int getIntVolatile(Object o, long offset); + + /** Volatile version of {@link #putInt(Object, long, int)} */ + @HotSpotIntrinsicCandidate + public native void putIntVolatile(Object o, long offset, int x); + + /** Volatile version of {@link #getBoolean(Object, long)} */ + @HotSpotIntrinsicCandidate + public native boolean getBooleanVolatile(Object o, long offset); + + /** Volatile version of {@link #putBoolean(Object, long, boolean)} */ + @HotSpotIntrinsicCandidate + public native void putBooleanVolatile(Object o, long offset, boolean x); + + /** Volatile version of {@link #getByte(Object, long)} */ + @HotSpotIntrinsicCandidate + public native byte getByteVolatile(Object o, long offset); + + /** Volatile version of {@link #putByte(Object, long, byte)} */ + @HotSpotIntrinsicCandidate + public native void putByteVolatile(Object o, long offset, byte x); + + /** Volatile version of {@link #getShort(Object, long)} */ + @HotSpotIntrinsicCandidate + public native short getShortVolatile(Object o, long offset); + + /** Volatile version of {@link #putShort(Object, long, short)} */ + @HotSpotIntrinsicCandidate + public native void putShortVolatile(Object o, long offset, short x); + + /** Volatile version of {@link #getChar(Object, long)} */ + @HotSpotIntrinsicCandidate + public native char getCharVolatile(Object o, long offset); + + /** Volatile version of {@link #putChar(Object, long, char)} */ + @HotSpotIntrinsicCandidate + public native void putCharVolatile(Object o, long offset, char x); + + /** Volatile version of {@link #getLong(Object, long)} */ + @HotSpotIntrinsicCandidate + public native long getLongVolatile(Object o, long offset); + + /** Volatile version of {@link #putLong(Object, long, long)} */ + @HotSpotIntrinsicCandidate + public native void putLongVolatile(Object o, long offset, long x); + + /** Volatile version of {@link #getFloat(Object, long)} */ + @HotSpotIntrinsicCandidate + public native float getFloatVolatile(Object o, long offset); + + /** Volatile version of {@link #putFloat(Object, long, float)} */ + @HotSpotIntrinsicCandidate + public native void putFloatVolatile(Object o, long offset, float x); + + /** Volatile version of {@link #getDouble(Object, long)} */ + @HotSpotIntrinsicCandidate + public native double getDoubleVolatile(Object o, long offset); + + /** Volatile version of {@link #putDouble(Object, long, double)} */ + @HotSpotIntrinsicCandidate + public native void putDoubleVolatile(Object o, long offset, double x); + + /** + * Version of {@link #putObjectVolatile(Object, long, Object)} + * that does not guarantee immediate visibility of the store to + * other threads. This method is generally only useful if the + * underlying field is a Java volatile (or if an array cell, one + * that is otherwise only accessed using volatile accesses). + * + * Corresponds to C11 atomic_store_explicit(..., memory_order_release). + */ + @HotSpotIntrinsicCandidate + public native void putOrderedObject(Object o, long offset, Object x); + + /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */ + @HotSpotIntrinsicCandidate + public native void putOrderedInt(Object o, long offset, int x); + + /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */ + @HotSpotIntrinsicCandidate + public native void putOrderedLong(Object o, long offset, long x); + + /** + * Unblocks the given thread blocked on {@code park}, or, if it is + * not blocked, causes the subsequent call to {@code park} not to + * block. Note: this operation is "unsafe" solely because the + * caller must somehow ensure that the thread has not been + * destroyed. Nothing special is usually required to ensure this + * when called from Java (in which there will ordinarily be a live + * reference to the thread) but this is not nearly-automatically + * so when calling from native code. + * + * @param thread the thread to unpark. + */ + @HotSpotIntrinsicCandidate + public native void unpark(Object thread); + + /** + * Blocks current thread, returning when a balancing + * {@code unpark} occurs, or a balancing {@code unpark} has + * already occurred, or the thread is interrupted, or, if not + * absolute and time is not zero, the given time nanoseconds have + * elapsed, or if absolute, the given deadline in milliseconds + * since Epoch has passed, or spuriously (i.e., returning for no + * "reason"). Note: This operation is in the Unsafe class only + * because {@code unpark} is, so it would be strange to place it + * elsewhere. + */ + @HotSpotIntrinsicCandidate + public native void park(boolean isAbsolute, long time); + + /** + * Gets the load average in the system run queue assigned + * to the available processors averaged over various periods of time. + * This method retrieves the given {@code nelem} samples and + * assigns to the elements of the given {@code loadavg} array. + * The system imposes a maximum of 3 samples, representing + * averages over the last 1, 5, and 15 minutes, respectively. + * + * @param loadavg an array of double of size nelems + * @param nelems the number of samples to be retrieved and + * must be 1 to 3. + * + * @return the number of samples actually retrieved; or -1 + * if the load average is unobtainable. + */ + public native int getLoadAverage(double[] loadavg, int nelems); + + // The following contain CAS-based Java implementations used on + // platforms not supporting native instructions + + /** + * Atomically adds the given value to the current value of a field + * or array element within the given object {@code o} + * at the given {@code offset}. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param delta the value to add + * @return the previous value + * @since 1.8 + */ + @HotSpotIntrinsicCandidate + public final int getAndAddInt(Object o, long offset, int delta) { + int v; + do { + v = getIntVolatile(o, offset); + } while (!compareAndSwapInt(o, offset, v, v + delta)); + return v; + } + + /** + * Atomically adds the given value to the current value of a field + * or array element within the given object {@code o} + * at the given {@code offset}. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param delta the value to add + * @return the previous value + * @since 1.8 + */ + @HotSpotIntrinsicCandidate + public final long getAndAddLong(Object o, long offset, long delta) { + long v; + do { + v = getLongVolatile(o, offset); + } while (!compareAndSwapLong(o, offset, v, v + delta)); + return v; + } + + /** + * Atomically exchanges the given value with the current value of + * a field or array element within the given object {@code o} + * at the given {@code offset}. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param newValue new value + * @return the previous value + * @since 1.8 + */ + @HotSpotIntrinsicCandidate + public final int getAndSetInt(Object o, long offset, int newValue) { + int v; + do { + v = getIntVolatile(o, offset); + } while (!compareAndSwapInt(o, offset, v, newValue)); + return v; + } + + /** + * Atomically exchanges the given value with the current value of + * a field or array element within the given object {@code o} + * at the given {@code offset}. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param newValue new value + * @return the previous value + * @since 1.8 + */ + @HotSpotIntrinsicCandidate + public final long getAndSetLong(Object o, long offset, long newValue) { + long v; + do { + v = getLongVolatile(o, offset); + } while (!compareAndSwapLong(o, offset, v, newValue)); + return v; + } + + /** + * Atomically exchanges the given reference value with the current + * reference value of a field or array element within the given + * object {@code o} at the given {@code offset}. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param newValue new value + * @return the previous value + * @since 1.8 + */ + @HotSpotIntrinsicCandidate + public final Object getAndSetObject(Object o, long offset, Object newValue) { + Object v; + do { + v = getObjectVolatile(o, offset); + } while (!compareAndSwapObject(o, offset, v, newValue)); + return v; + } + + + /** + * Ensures that loads before the fence will not be reordered with loads and + * stores after the fence; a "LoadLoad plus LoadStore barrier". + * + * Corresponds to C11 atomic_thread_fence(memory_order_acquire) + * (an "acquire fence"). + * + * A pure LoadLoad fence is not provided, since the addition of LoadStore + * is almost always desired, and most current hardware instructions that + * provide a LoadLoad barrier also provide a LoadStore barrier for free. + * @since 1.8 + */ + @HotSpotIntrinsicCandidate + public native void loadFence(); + + /** + * Ensures that loads and stores before the fence will not be reordered with + * stores after the fence; a "StoreStore plus LoadStore barrier". + * + * Corresponds to C11 atomic_thread_fence(memory_order_release) + * (a "release fence"). + * + * A pure StoreStore fence is not provided, since the addition of LoadStore + * is almost always desired, and most current hardware instructions that + * provide a StoreStore barrier also provide a LoadStore barrier for free. + * @since 1.8 + */ + @HotSpotIntrinsicCandidate + public native void storeFence(); + + /** + * Ensures that loads and stores before the fence will not be reordered + * with loads and stores after the fence. Implies the effects of both + * loadFence() and storeFence(), and in addition, the effect of a StoreLoad + * barrier. + * + * Corresponds to C11 atomic_thread_fence(memory_order_seq_cst). + * @since 1.8 + */ + @HotSpotIntrinsicCandidate + public native void fullFence(); + + /** + * Throws IllegalAccessError; for use by the VM for access control + * error support. + * @since 1.8 + */ + private static void throwIllegalAccessError() { + throw new IllegalAccessError(); + } + + /** + * @return Returns true if the native byte ordering of this + * platform is big-endian, false if it is little-endian. + */ + public final boolean isBigEndian() { return BE; } + + /** + * @return Returns true if this platform is capable of performing + * accesses at addresses which are not aligned for the type of the + * primitive type being accessed, false otherwise. + */ + public final boolean unalignedAccess() { return unalignedAccess; } + + /** + * Fetches a value at some byte offset into a given Java object. + * More specifically, fetches a value within the given object + * <code>o</code> at the given offset, or (if <code>o</code> is + * null) from the memory address whose numerical value is the + * given offset. <p> + * + * The specification of this method is the same as {@link + * #getLong(Object, long)} except that the offset does not need to + * have been obtained from {@link #objectFieldOffset} on the + * {@link java.lang.reflect.Field} of some Java field. The value + * in memory is raw data, and need not correspond to any Java + * variable. Unless <code>o</code> is null, the value accessed + * must be entirely within the allocated object. The endianness + * of the value in memory is the endianness of the native platform. + * + * <p> The read will be atomic with respect to the largest power + * of two that divides the GCD of the offset and the storage size. + * For example, getLongUnaligned will make atomic reads of 2-, 4-, + * or 8-byte storage units if the offset is zero mod 2, 4, or 8, + * respectively. There are no other guarantees of atomicity. + * <p> + * 8-byte atomicity is only guaranteed on platforms on which + * support atomic accesses to longs. + * + * @param o Java heap object in which the value resides, if any, else + * null + * @param offset The offset in bytes from the start of the object + * @return the value fetched from the indicated object + * @throws RuntimeException No defined exceptions are thrown, not even + * {@link NullPointerException} + * @since 1.9 + */ + @HotSpotIntrinsicCandidate + public final long getLongUnaligned(Object o, long offset) { + if ((offset & 7) == 0) { + return getLong(o, offset); + } else if ((offset & 3) == 0) { + return makeLong(getInt(o, offset), + getInt(o, offset + 4)); + } else if ((offset & 1) == 0) { + return makeLong(getShort(o, offset), + getShort(o, offset + 2), + getShort(o, offset + 4), + getShort(o, offset + 6)); + } else { + return makeLong(getByte(o, offset), + getByte(o, offset + 1), + getByte(o, offset + 2), + getByte(o, offset + 3), + getByte(o, offset + 4), + getByte(o, offset + 5), + getByte(o, offset + 6), + getByte(o, offset + 7)); + } + } + /** + * As {@link #getLongUnaligned(Object, long)} but with an + * additional argument which specifies the endianness of the value + * as stored in memory. + * + * @param o Java heap object in which the variable resides + * @param offset The offset in bytes from the start of the object + * @param bigEndian The endianness of the value + * @return the value fetched from the indicated object + * @since 1.9 + */ + public final long getLongUnaligned(Object o, long offset, boolean bigEndian) { + return convEndian(bigEndian, getLongUnaligned(o, offset)); + } + + /** @see #getLongUnaligned(Object, long) */ + @HotSpotIntrinsicCandidate + public final int getIntUnaligned(Object o, long offset) { + if ((offset & 3) == 0) { + return getInt(o, offset); + } else if ((offset & 1) == 0) { + return makeInt(getShort(o, offset), + getShort(o, offset + 2)); + } else { + return makeInt(getByte(o, offset), + getByte(o, offset + 1), + getByte(o, offset + 2), + getByte(o, offset + 3)); + } + } + /** @see #getLongUnaligned(Object, long, boolean) */ + public final int getIntUnaligned(Object o, long offset, boolean bigEndian) { + return convEndian(bigEndian, getIntUnaligned(o, offset)); + } + + /** @see #getLongUnaligned(Object, long) */ + @HotSpotIntrinsicCandidate + public final short getShortUnaligned(Object o, long offset) { + if ((offset & 1) == 0) { + return getShort(o, offset); + } else { + return makeShort(getByte(o, offset), + getByte(o, offset + 1)); + } + } + /** @see #getLongUnaligned(Object, long, boolean) */ + public final short getShortUnaligned(Object o, long offset, boolean bigEndian) { + return convEndian(bigEndian, getShortUnaligned(o, offset)); + } + + /** @see #getLongUnaligned(Object, long) */ + @HotSpotIntrinsicCandidate + public final char getCharUnaligned(Object o, long offset) { + return (char)getShortUnaligned(o, offset); + } + + /** @see #getLongUnaligned(Object, long, boolean) */ + public final char getCharUnaligned(Object o, long offset, boolean bigEndian) { + return convEndian(bigEndian, getCharUnaligned(o, offset)); + } + + /** + * Stores a value at some byte offset into a given Java object. + * <p> + * The specification of this method is the same as {@link + * #getLong(Object, long)} except that the offset does not need to + * have been obtained from {@link #objectFieldOffset} on the + * {@link java.lang.reflect.Field} of some Java field. The value + * in memory is raw data, and need not correspond to any Java + * variable. The endianness of the value in memory is the + * endianness of the native platform. + * <p> + * The write will be atomic with respect to the largest power of + * two that divides the GCD of the offset and the storage size. + * For example, putLongUnaligned will make atomic writes of 2-, 4-, + * or 8-byte storage units if the offset is zero mod 2, 4, or 8, + * respectively. There are no other guarantees of atomicity. + * <p> + * 8-byte atomicity is only guaranteed on platforms on which + * support atomic accesses to longs. + * + * @param o Java heap object in which the value resides, if any, else + * null + * @param offset The offset in bytes from the start of the object + * @param x the value to store + * @throws RuntimeException No defined exceptions are thrown, not even + * {@link NullPointerException} + * @since 1.9 + */ + @HotSpotIntrinsicCandidate + public final void putLongUnaligned(Object o, long offset, long x) { + if ((offset & 7) == 0) { + putLong(o, offset, x); + } else if ((offset & 3) == 0) { + putLongParts(o, offset, + (int)(x >> 0), + (int)(x >>> 32)); + } else if ((offset & 1) == 0) { + putLongParts(o, offset, + (short)(x >>> 0), + (short)(x >>> 16), + (short)(x >>> 32), + (short)(x >>> 48)); + } else { + putLongParts(o, offset, + (byte)(x >>> 0), + (byte)(x >>> 8), + (byte)(x >>> 16), + (byte)(x >>> 24), + (byte)(x >>> 32), + (byte)(x >>> 40), + (byte)(x >>> 48), + (byte)(x >>> 56)); + } + } + + /** + * As {@link #putLongUnaligned(Object, long, long)} but with an additional + * argument which specifies the endianness of the value as stored in memory. + * @param o Java heap object in which the value resides + * @param offset The offset in bytes from the start of the object + * @param x the value to store + * @param bigEndian The endianness of the value + * @throws RuntimeException No defined exceptions are thrown, not even + * {@link NullPointerException} + * @since 1.9 + */ + public final void putLongUnaligned(Object o, long offset, long x, boolean bigEndian) { + putLongUnaligned(o, offset, convEndian(bigEndian, x)); + } + + /** @see #putLongUnaligned(Object, long, long) */ + @HotSpotIntrinsicCandidate + public final void putIntUnaligned(Object o, long offset, int x) { + if ((offset & 3) == 0) { + putInt(o, offset, x); + } else if ((offset & 1) == 0) { + putIntParts(o, offset, + (short)(x >> 0), + (short)(x >>> 16)); + } else { + putIntParts(o, offset, + (byte)(x >>> 0), + (byte)(x >>> 8), + (byte)(x >>> 16), + (byte)(x >>> 24)); + } + } + /** @see #putLongUnaligned(Object, long, long, boolean) */ + public final void putIntUnaligned(Object o, long offset, int x, boolean bigEndian) { + putIntUnaligned(o, offset, convEndian(bigEndian, x)); + } + + /** @see #putLongUnaligned(Object, long, long) */ + @HotSpotIntrinsicCandidate + public final void putShortUnaligned(Object o, long offset, short x) { + if ((offset & 1) == 0) { + putShort(o, offset, x); + } else { + putShortParts(o, offset, + (byte)(x >>> 0), + (byte)(x >>> 8)); + } + } + /** @see #putLongUnaligned(Object, long, long, boolean) */ + public final void putShortUnaligned(Object o, long offset, short x, boolean bigEndian) { + putShortUnaligned(o, offset, convEndian(bigEndian, x)); + } + + /** @see #putLongUnaligned(Object, long, long) */ + @HotSpotIntrinsicCandidate + public final void putCharUnaligned(Object o, long offset, char x) { + putShortUnaligned(o, offset, (short)x); + } + /** @see #putLongUnaligned(Object, long, long, boolean) */ + public final void putCharUnaligned(Object o, long offset, char x, boolean bigEndian) { + putCharUnaligned(o, offset, convEndian(bigEndian, x)); + } + + // JVM interface methods + private native boolean unalignedAccess0(); + private native boolean isBigEndian0(); + + // BE is true iff the native endianness of this platform is big. + private static final boolean BE = theUnsafe.isBigEndian0(); + + // unalignedAccess is true iff this platform can perform unaligned accesses. + private static final boolean unalignedAccess = theUnsafe.unalignedAccess0(); + + private static int pickPos(int top, int pos) { return BE ? top - pos : pos; } + + // These methods construct integers from bytes. The byte ordering + // is the native endianness of this platform. + private static long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) { + return ((toUnsignedLong(i0) << pickPos(56, 0)) + | (toUnsignedLong(i1) << pickPos(56, 8)) + | (toUnsignedLong(i2) << pickPos(56, 16)) + | (toUnsignedLong(i3) << pickPos(56, 24)) + | (toUnsignedLong(i4) << pickPos(56, 32)) + | (toUnsignedLong(i5) << pickPos(56, 40)) + | (toUnsignedLong(i6) << pickPos(56, 48)) + | (toUnsignedLong(i7) << pickPos(56, 56))); + } + private static long makeLong(short i0, short i1, short i2, short i3) { + return ((toUnsignedLong(i0) << pickPos(48, 0)) + | (toUnsignedLong(i1) << pickPos(48, 16)) + | (toUnsignedLong(i2) << pickPos(48, 32)) + | (toUnsignedLong(i3) << pickPos(48, 48))); + } + private static long makeLong(int i0, int i1) { + return (toUnsignedLong(i0) << pickPos(32, 0)) + | (toUnsignedLong(i1) << pickPos(32, 32)); + } + private static int makeInt(short i0, short i1) { + return (toUnsignedInt(i0) << pickPos(16, 0)) + | (toUnsignedInt(i1) << pickPos(16, 16)); + } + private static int makeInt(byte i0, byte i1, byte i2, byte i3) { + return ((toUnsignedInt(i0) << pickPos(24, 0)) + | (toUnsignedInt(i1) << pickPos(24, 8)) + | (toUnsignedInt(i2) << pickPos(24, 16)) + | (toUnsignedInt(i3) << pickPos(24, 24))); + } + private static short makeShort(byte i0, byte i1) { + return (short)((toUnsignedInt(i0) << pickPos(8, 0)) + | (toUnsignedInt(i1) << pickPos(8, 8))); + } + + private static byte pick(byte le, byte be) { return BE ? be : le; } + private static short pick(short le, short be) { return BE ? be : le; } + private static int pick(int le, int be) { return BE ? be : le; } + + // These methods write integers to memory from smaller parts + // provided by their caller. The ordering in which these parts + // are written is the native endianness of this platform. + private void putLongParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) { + putByte(o, offset + 0, pick(i0, i7)); + putByte(o, offset + 1, pick(i1, i6)); + putByte(o, offset + 2, pick(i2, i5)); + putByte(o, offset + 3, pick(i3, i4)); + putByte(o, offset + 4, pick(i4, i3)); + putByte(o, offset + 5, pick(i5, i2)); + putByte(o, offset + 6, pick(i6, i1)); + putByte(o, offset + 7, pick(i7, i0)); + } + private void putLongParts(Object o, long offset, short i0, short i1, short i2, short i3) { + putShort(o, offset + 0, pick(i0, i3)); + putShort(o, offset + 2, pick(i1, i2)); + putShort(o, offset + 4, pick(i2, i1)); + putShort(o, offset + 6, pick(i3, i0)); + } + private void putLongParts(Object o, long offset, int i0, int i1) { + putInt(o, offset + 0, pick(i0, i1)); + putInt(o, offset + 4, pick(i1, i0)); + } + private void putIntParts(Object o, long offset, short i0, short i1) { + putShort(o, offset + 0, pick(i0, i1)); + putShort(o, offset + 2, pick(i1, i0)); + } + private void putIntParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3) { + putByte(o, offset + 0, pick(i0, i3)); + putByte(o, offset + 1, pick(i1, i2)); + putByte(o, offset + 2, pick(i2, i1)); + putByte(o, offset + 3, pick(i3, i0)); + } + private void putShortParts(Object o, long offset, byte i0, byte i1) { + putByte(o, offset + 0, pick(i0, i1)); + putByte(o, offset + 1, pick(i1, i0)); + } + + // Zero-extend an integer + private static int toUnsignedInt(byte n) { return n & 0xff; } + private static int toUnsignedInt(short n) { return n & 0xffff; } + private static long toUnsignedLong(byte n) { return n & 0xffl; } + private static long toUnsignedLong(short n) { return n & 0xffffl; } + private static long toUnsignedLong(int n) { return n & 0xffffffffl; } + + // Maybe byte-reverse an integer + private static char convEndian(boolean big, char n) { return big == BE ? n : Character.reverseBytes(n); } + private static short convEndian(boolean big, short n) { return big == BE ? n : Short.reverseBytes(n) ; } + private static int convEndian(boolean big, int n) { return big == BE ? n : Integer.reverseBytes(n) ; } + private static long convEndian(boolean big, long n) { return big == BE ? n : Long.reverseBytes(n) ; } +} diff --git a/jdk/src/java.base/share/classes/sun/invoke/anon/AnonymousClassLoader.java b/jdk/src/java.base/share/classes/sun/invoke/anon/AnonymousClassLoader.java index 60544e25f387ba9e6045698e8c87779580f5ebe9..6c5cb3f5563d9e488c788ceef3f2d7dfb80e9109 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/anon/AnonymousClassLoader.java +++ b/jdk/src/java.base/share/classes/sun/invoke/anon/AnonymousClassLoader.java @@ -78,7 +78,7 @@ public class AnonymousClassLoader { this.hostClass = hostClass; } - public static AnonymousClassLoader make(sun.misc.Unsafe unsafe, Class<?> hostClass) { + public static AnonymousClassLoader make(jdk.internal.misc.Unsafe unsafe, Class<?> hostClass) { if (unsafe == null) throw new NullPointerException(); return new AnonymousClassLoader(hostClass); } @@ -189,13 +189,13 @@ public class AnonymousClassLoader { private static int fakeNameCounter = 99999; // ignore two warnings on this line: - private static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + private static jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); // preceding line requires that this class be on the boot class path private static final Method defineAnonymousClass; static { Method dac = null; - Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass(); + Class<? extends jdk.internal.misc.Unsafe> unsafeClass = unsafe.getClass(); try { dac = unsafeClass.getMethod("defineAnonymousClass", Class.class, diff --git a/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java b/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java index e69330b68464569f5d1f793671ee540067585fe6..ef27a08c132fac3c44cd08e17f47a312301dacb9 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java +++ b/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java @@ -27,18 +27,19 @@ package sun.invoke.util; public enum Wrapper { // wrapperType primitiveType char zero emptyArray format - BOOLEAN( Boolean.class, boolean.class, 'Z', (Boolean)false, new boolean[0], Format.unsigned( 1)), + BOOLEAN( Boolean.class, boolean.class, 'Z', Boolean.FALSE, new boolean[0], Format.unsigned( 1)), // These must be in the order defined for widening primitive conversions in JLS 5.1.2 - BYTE ( Byte.class, byte.class, 'B', (Byte)(byte)0, new byte[0], Format.signed( 8)), - SHORT ( Short.class, short.class, 'S', (Short)(short)0, new short[0], Format.signed( 16)), - CHAR (Character.class, char.class, 'C', (Character)(char)0, new char[0], Format.unsigned(16)), - INT ( Integer.class, int.class, 'I', (Integer)/*(int)*/0, new int[0], Format.signed( 32)), - LONG ( Long.class, long.class, 'J', (Long)(long)0, new long[0], Format.signed( 64)), - FLOAT ( Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)), - DOUBLE ( Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)), - OBJECT ( Object.class, Object.class, 'L', null, new Object[0], Format.other( 1)), + // Avoid boxing integral types here to defer initialization of internal caches + BYTE ( Byte.class, byte.class, 'B', new Byte((byte)0), new byte[0], Format.signed( 8)), + SHORT ( Short.class, short.class, 'S', new Short((short)0), new short[0], Format.signed( 16)), + CHAR (Character.class, char.class, 'C', new Character((char)0), new char[0], Format.unsigned(16)), + INT ( Integer.class, int.class, 'I', new Integer(0), new int[0], Format.signed( 32)), + LONG ( Long.class, long.class, 'J', new Long(0), new long[0], Format.signed( 64)), + FLOAT ( Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)), + DOUBLE ( Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)), + OBJECT ( Object.class, Object.class, 'L', null, new Object[0], Format.other( 1)), // VOID must be the last type, since it is "assignable" from any other type: - VOID ( Void.class, void.class, 'V', null, null, Format.other( 0)), + VOID ( Void.class, void.class, 'V', null, null, Format.other( 0)), ; private final Class<?> wrapperType; diff --git a/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java b/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java index 78a0a185f0a5e625be4fa46b4ab7fec83924e433..a9c129cd79e6c708ec4b4c3acb1458e4d036c508 100644 --- a/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java +++ b/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java @@ -36,7 +36,7 @@ import java.util.concurrent.atomic.AtomicInteger; * ThreadGroup and supports the ability to erase ThreadLocals. */ public final class InnocuousThread extends ManagedLocalsThread { - private static final Unsafe UNSAFE; + private static final jdk.internal.misc.Unsafe UNSAFE; private static final ThreadGroup INNOCUOUSTHREADGROUP; private static final AccessControlContext ACC; private static final long INHERITEDACCESSCONTROLCONTEXT; @@ -92,7 +92,7 @@ public final class InnocuousThread extends ManagedLocalsThread { }); // Find and use topmost ThreadGroup as parent of new group - UNSAFE = Unsafe.getUnsafe(); + UNSAFE = jdk.internal.misc.Unsafe.getUnsafe(); Class<?> tk = Thread.class; Class<?> gk = ThreadGroup.class; diff --git a/jdk/src/java.base/share/classes/sun/misc/ManagedLocalsThread.java b/jdk/src/java.base/share/classes/sun/misc/ManagedLocalsThread.java index f520ca384b66b8718d065b53b831b3b06f994ca9..58d9013c2614fbc477b2fbb7a8fd000f6e225761 100644 --- a/jdk/src/java.base/share/classes/sun/misc/ManagedLocalsThread.java +++ b/jdk/src/java.base/share/classes/sun/misc/ManagedLocalsThread.java @@ -30,7 +30,7 @@ package sun.misc; * locals erased on construction. */ public class ManagedLocalsThread 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; @@ -77,7 +77,7 @@ public class ManagedLocalsThread extends Thread { } static { - UNSAFE = Unsafe.getUnsafe(); + UNSAFE = jdk.internal.misc.Unsafe.getUnsafe(); Class<?> t = Thread.class; try { THREAD_LOCALS = UNSAFE.objectFieldOffset diff --git a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java index b6cca9d8f146f90fddcae8ee46aac06953cf4e72..6a4775a4c3a040752e4f5c78ccd921cdff3edc7d 100644 --- a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java @@ -1036,355 +1036,8 @@ public final class Unsafe { throw new IllegalAccessError(); } - /** - * @return Returns true if the native byte ordering of this - * platform is big-endian, false if it is little-endian. - */ - public final boolean isBigEndian() { return BE; } - - /** - * @return Returns true if this platform is capable of performing - * accesses at addresses which are not aligned for the type of the - * primitive type being accessed, false otherwise. - */ - public final boolean unalignedAccess() { return unalignedAccess; } - - /** - * Fetches a value at some byte offset into a given Java object. - * More specifically, fetches a value within the given object - * <code>o</code> at the given offset, or (if <code>o</code> is - * null) from the memory address whose numerical value is the - * given offset. <p> - * - * The specification of this method is the same as {@link - * #getLong(Object, long)} except that the offset does not need to - * have been obtained from {@link #objectFieldOffset} on the - * {@link java.lang.reflect.Field} of some Java field. The value - * in memory is raw data, and need not correspond to any Java - * variable. Unless <code>o</code> is null, the value accessed - * must be entirely within the allocated object. The endianness - * of the value in memory is the endianness of the native platform. - * - * <p> The read will be atomic with respect to the largest power - * of two that divides the GCD of the offset and the storage size. - * For example, getLongUnaligned will make atomic reads of 2-, 4-, - * or 8-byte storage units if the offset is zero mod 2, 4, or 8, - * respectively. There are no other guarantees of atomicity. - * <p> - * 8-byte atomicity is only guaranteed on platforms on which - * support atomic accesses to longs. - * - * @param o Java heap object in which the value resides, if any, else - * null - * @param offset The offset in bytes from the start of the object - * @return the value fetched from the indicated object - * @throws RuntimeException No defined exceptions are thrown, not even - * {@link NullPointerException} - * @since 1.9 - */ - @HotSpotIntrinsicCandidate - public final long getLongUnaligned(Object o, long offset) { - if ((offset & 7) == 0) { - return getLong(o, offset); - } else if ((offset & 3) == 0) { - return makeLong(getInt(o, offset), - getInt(o, offset + 4)); - } else if ((offset & 1) == 0) { - return makeLong(getShort(o, offset), - getShort(o, offset + 2), - getShort(o, offset + 4), - getShort(o, offset + 6)); - } else { - return makeLong(getByte(o, offset), - getByte(o, offset + 1), - getByte(o, offset + 2), - getByte(o, offset + 3), - getByte(o, offset + 4), - getByte(o, offset + 5), - getByte(o, offset + 6), - getByte(o, offset + 7)); - } - } - /** - * As {@link #getLongUnaligned(Object, long)} but with an - * additional argument which specifies the endianness of the value - * as stored in memory. - * - * @param o Java heap object in which the variable resides - * @param offset The offset in bytes from the start of the object - * @param bigEndian The endianness of the value - * @return the value fetched from the indicated object - * @since 1.9 - */ - public final long getLongUnaligned(Object o, long offset, boolean bigEndian) { - return convEndian(bigEndian, getLongUnaligned(o, offset)); - } - - /** @see #getLongUnaligned(Object, long) */ - @HotSpotIntrinsicCandidate - public final int getIntUnaligned(Object o, long offset) { - if ((offset & 3) == 0) { - return getInt(o, offset); - } else if ((offset & 1) == 0) { - return makeInt(getShort(o, offset), - getShort(o, offset + 2)); - } else { - return makeInt(getByte(o, offset), - getByte(o, offset + 1), - getByte(o, offset + 2), - getByte(o, offset + 3)); - } - } - /** @see #getLongUnaligned(Object, long, boolean) */ - public final int getIntUnaligned(Object o, long offset, boolean bigEndian) { - return convEndian(bigEndian, getIntUnaligned(o, offset)); - } - - /** @see #getLongUnaligned(Object, long) */ - @HotSpotIntrinsicCandidate - public final short getShortUnaligned(Object o, long offset) { - if ((offset & 1) == 0) { - return getShort(o, offset); - } else { - return makeShort(getByte(o, offset), - getByte(o, offset + 1)); - } - } - /** @see #getLongUnaligned(Object, long, boolean) */ - public final short getShortUnaligned(Object o, long offset, boolean bigEndian) { - return convEndian(bigEndian, getShortUnaligned(o, offset)); - } - - /** @see #getLongUnaligned(Object, long) */ - @HotSpotIntrinsicCandidate - public final char getCharUnaligned(Object o, long offset) { - return (char)getShortUnaligned(o, offset); - } - - /** @see #getLongUnaligned(Object, long, boolean) */ - public final char getCharUnaligned(Object o, long offset, boolean bigEndian) { - return convEndian(bigEndian, getCharUnaligned(o, offset)); - } - - /** - * Stores a value at some byte offset into a given Java object. - * <p> - * The specification of this method is the same as {@link - * #getLong(Object, long)} except that the offset does not need to - * have been obtained from {@link #objectFieldOffset} on the - * {@link java.lang.reflect.Field} of some Java field. The value - * in memory is raw data, and need not correspond to any Java - * variable. The endianness of the value in memory is the - * endianness of the native platform. - * <p> - * The write will be atomic with respect to the largest power of - * two that divides the GCD of the offset and the storage size. - * For example, putLongUnaligned will make atomic writes of 2-, 4-, - * or 8-byte storage units if the offset is zero mod 2, 4, or 8, - * respectively. There are no other guarantees of atomicity. - * <p> - * 8-byte atomicity is only guaranteed on platforms on which - * support atomic accesses to longs. - * - * @param o Java heap object in which the value resides, if any, else - * null - * @param offset The offset in bytes from the start of the object - * @param x the value to store - * @throws RuntimeException No defined exceptions are thrown, not even - * {@link NullPointerException} - * @since 1.9 - */ - @HotSpotIntrinsicCandidate - public final void putLongUnaligned(Object o, long offset, long x) { - if ((offset & 7) == 0) { - putLong(o, offset, x); - } else if ((offset & 3) == 0) { - putLongParts(o, offset, - (int)(x >> 0), - (int)(x >>> 32)); - } else if ((offset & 1) == 0) { - putLongParts(o, offset, - (short)(x >>> 0), - (short)(x >>> 16), - (short)(x >>> 32), - (short)(x >>> 48)); - } else { - putLongParts(o, offset, - (byte)(x >>> 0), - (byte)(x >>> 8), - (byte)(x >>> 16), - (byte)(x >>> 24), - (byte)(x >>> 32), - (byte)(x >>> 40), - (byte)(x >>> 48), - (byte)(x >>> 56)); - } - } - - /** - * As {@link #putLongUnaligned(Object, long, long)} but with an additional - * argument which specifies the endianness of the value as stored in memory. - * @param o Java heap object in which the value resides - * @param offset The offset in bytes from the start of the object - * @param x the value to store - * @param bigEndian The endianness of the value - * @throws RuntimeException No defined exceptions are thrown, not even - * {@link NullPointerException} - * @since 1.9 - */ - public final void putLongUnaligned(Object o, long offset, long x, boolean bigEndian) { - putLongUnaligned(o, offset, convEndian(bigEndian, x)); - } - - /** @see #putLongUnaligned(Object, long, long) */ - @HotSpotIntrinsicCandidate - public final void putIntUnaligned(Object o, long offset, int x) { - if ((offset & 3) == 0) { - putInt(o, offset, x); - } else if ((offset & 1) == 0) { - putIntParts(o, offset, - (short)(x >> 0), - (short)(x >>> 16)); - } else { - putIntParts(o, offset, - (byte)(x >>> 0), - (byte)(x >>> 8), - (byte)(x >>> 16), - (byte)(x >>> 24)); - } - } - /** @see #putLongUnaligned(Object, long, long, boolean) */ - public final void putIntUnaligned(Object o, long offset, int x, boolean bigEndian) { - putIntUnaligned(o, offset, convEndian(bigEndian, x)); - } - - /** @see #putLongUnaligned(Object, long, long) */ - @HotSpotIntrinsicCandidate - public final void putShortUnaligned(Object o, long offset, short x) { - if ((offset & 1) == 0) { - putShort(o, offset, x); - } else { - putShortParts(o, offset, - (byte)(x >>> 0), - (byte)(x >>> 8)); - } - } - /** @see #putLongUnaligned(Object, long, long, boolean) */ - public final void putShortUnaligned(Object o, long offset, short x, boolean bigEndian) { - putShortUnaligned(o, offset, convEndian(bigEndian, x)); - } - - /** @see #putLongUnaligned(Object, long, long) */ - @HotSpotIntrinsicCandidate - public final void putCharUnaligned(Object o, long offset, char x) { - putShortUnaligned(o, offset, (short)x); - } - /** @see #putLongUnaligned(Object, long, long, boolean) */ - public final void putCharUnaligned(Object o, long offset, char x, boolean bigEndian) { - putCharUnaligned(o, offset, convEndian(bigEndian, x)); - } - // JVM interface methods private native boolean unalignedAccess0(); private native boolean isBigEndian0(); - // BE is true iff the native endianness of this platform is big. - private static final boolean BE = theUnsafe.isBigEndian0(); - - // unalignedAccess is true iff this platform can perform unaligned accesses. - private static final boolean unalignedAccess = theUnsafe.unalignedAccess0(); - - private static int pickPos(int top, int pos) { return BE ? top - pos : pos; } - - // These methods construct integers from bytes. The byte ordering - // is the native endianness of this platform. - private static long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) { - return ((toUnsignedLong(i0) << pickPos(56, 0)) - | (toUnsignedLong(i1) << pickPos(56, 8)) - | (toUnsignedLong(i2) << pickPos(56, 16)) - | (toUnsignedLong(i3) << pickPos(56, 24)) - | (toUnsignedLong(i4) << pickPos(56, 32)) - | (toUnsignedLong(i5) << pickPos(56, 40)) - | (toUnsignedLong(i6) << pickPos(56, 48)) - | (toUnsignedLong(i7) << pickPos(56, 56))); - } - private static long makeLong(short i0, short i1, short i2, short i3) { - return ((toUnsignedLong(i0) << pickPos(48, 0)) - | (toUnsignedLong(i1) << pickPos(48, 16)) - | (toUnsignedLong(i2) << pickPos(48, 32)) - | (toUnsignedLong(i3) << pickPos(48, 48))); - } - private static long makeLong(int i0, int i1) { - return (toUnsignedLong(i0) << pickPos(32, 0)) - | (toUnsignedLong(i1) << pickPos(32, 32)); - } - private static int makeInt(short i0, short i1) { - return (toUnsignedInt(i0) << pickPos(16, 0)) - | (toUnsignedInt(i1) << pickPos(16, 16)); - } - private static int makeInt(byte i0, byte i1, byte i2, byte i3) { - return ((toUnsignedInt(i0) << pickPos(24, 0)) - | (toUnsignedInt(i1) << pickPos(24, 8)) - | (toUnsignedInt(i2) << pickPos(24, 16)) - | (toUnsignedInt(i3) << pickPos(24, 24))); - } - private static short makeShort(byte i0, byte i1) { - return (short)((toUnsignedInt(i0) << pickPos(8, 0)) - | (toUnsignedInt(i1) << pickPos(8, 8))); - } - - private static byte pick(byte le, byte be) { return BE ? be : le; } - private static short pick(short le, short be) { return BE ? be : le; } - private static int pick(int le, int be) { return BE ? be : le; } - - // These methods write integers to memory from smaller parts - // provided by their caller. The ordering in which these parts - // are written is the native endianness of this platform. - private void putLongParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) { - putByte(o, offset + 0, pick(i0, i7)); - putByte(o, offset + 1, pick(i1, i6)); - putByte(o, offset + 2, pick(i2, i5)); - putByte(o, offset + 3, pick(i3, i4)); - putByte(o, offset + 4, pick(i4, i3)); - putByte(o, offset + 5, pick(i5, i2)); - putByte(o, offset + 6, pick(i6, i1)); - putByte(o, offset + 7, pick(i7, i0)); - } - private void putLongParts(Object o, long offset, short i0, short i1, short i2, short i3) { - putShort(o, offset + 0, pick(i0, i3)); - putShort(o, offset + 2, pick(i1, i2)); - putShort(o, offset + 4, pick(i2, i1)); - putShort(o, offset + 6, pick(i3, i0)); - } - private void putLongParts(Object o, long offset, int i0, int i1) { - putInt(o, offset + 0, pick(i0, i1)); - putInt(o, offset + 4, pick(i1, i0)); - } - private void putIntParts(Object o, long offset, short i0, short i1) { - putShort(o, offset + 0, pick(i0, i1)); - putShort(o, offset + 2, pick(i1, i0)); - } - private void putIntParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3) { - putByte(o, offset + 0, pick(i0, i3)); - putByte(o, offset + 1, pick(i1, i2)); - putByte(o, offset + 2, pick(i2, i1)); - putByte(o, offset + 3, pick(i3, i0)); - } - private void putShortParts(Object o, long offset, byte i0, byte i1) { - putByte(o, offset + 0, pick(i0, i1)); - putByte(o, offset + 1, pick(i1, i0)); - } - - // Zero-extend an integer - private static int toUnsignedInt(byte n) { return n & 0xff; } - private static int toUnsignedInt(short n) { return n & 0xffff; } - private static long toUnsignedLong(byte n) { return n & 0xffl; } - private static long toUnsignedLong(short n) { return n & 0xffffl; } - private static long toUnsignedLong(int n) { return n & 0xffffffffl; } - - // Maybe byte-reverse an integer - private static char convEndian(boolean big, char n) { return big == BE ? n : Character.reverseBytes(n); } - private static short convEndian(boolean big, short n) { return big == BE ? n : Short.reverseBytes(n) ; } - private static int convEndian(boolean big, int n) { return big == BE ? n : Integer.reverseBytes(n) ; } - private static long convEndian(boolean big, long n) { return big == BE ? n : Long.reverseBytes(n) ; } } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/NativeObject.java b/jdk/src/java.base/share/classes/sun/nio/ch/NativeObject.java index e4e4366289af9d86a03bb105812a4b147d06e8e8..839b64df8add9b72bd716b237063c2e36e776702 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/NativeObject.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/NativeObject.java @@ -29,7 +29,7 @@ package sun.nio.ch; // Formerly in sun.misc import java.nio.ByteOrder; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; // ## In the fullness of time, this class will be eliminated diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java index 614850577e04186645ebff24b56ddd9c94a67c23..fd4281499997ad56499ee93bdd938ff2fd792750 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java @@ -35,7 +35,7 @@ import java.nio.channels.*; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.misc.Cleaner; import sun.security.action.GetPropertyAction; diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/ArrayDecoder.java b/jdk/src/java.base/share/classes/sun/nio/cs/ArrayDecoder.java index 6b0abe98d4b586d22e9a98d892b65087e834a263..0ba73309524f6759c80167369e3c0dd1263e4134 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/ArrayDecoder.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/ArrayDecoder.java @@ -32,4 +32,8 @@ package sun.nio.cs; public interface ArrayDecoder { int decode(byte[] src, int off, int len, char[] dst); + + default boolean isASCIICompatible() { + return false; + } } diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/ArrayEncoder.java b/jdk/src/java.base/share/classes/sun/nio/cs/ArrayEncoder.java index 2ef46e7f3bf1cb12e5a0b27f8c8a0064650c8bfc..b4ced428b33abd5326bbe347238132c1de270c05 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/ArrayEncoder.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/ArrayEncoder.java @@ -26,10 +26,24 @@ package sun.nio.cs; /* - * FastPath char[]->byte[] encoder, REPLACE on malformed input or + * FastPath char[]/byte[] -> byte[] encoder, REPLACE on malformed input or * unmappable input. */ public interface ArrayEncoder { + + // is only used by j.u.zip.ZipCoder for utf8 int encode(char[] src, int off, int len, byte[] dst); + + default int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) { + return -1; + } + + default int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) { + return -1; + } + + default boolean isASCIICompatible() { + return false; + } } diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/DoubleByte.java b/jdk/src/java.base/share/classes/sun/nio/cs/DoubleByte.java index 6121ab282d8b8d0fe42410e5f695399554524a90..9f8d97fdb39c219ccc0b3b8582cf1dd7cd3fd473 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/DoubleByte.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/DoubleByte.java @@ -115,6 +115,7 @@ public class DoubleByte { final char[] b2cSB; final int b2Min; final int b2Max; + final boolean isASCIICompatible; // for SimpleEUC override protected CoderResult crMalformedOrUnderFlow(int b) { @@ -132,16 +133,23 @@ public class DoubleByte { public Decoder(Charset cs, float avgcpb, float maxcpb, char[][] b2c, char[] b2cSB, - int b2Min, int b2Max) { + int b2Min, int b2Max, + boolean isASCIICompatible) { super(cs, avgcpb, maxcpb); this.b2c = b2c; this.b2cSB = b2cSB; this.b2Min = b2Min; this.b2Max = b2Max; + this.isASCIICompatible = isASCIICompatible; + } + + public Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max, + boolean isASCIICompatible) { + this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max, isASCIICompatible); } public Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) { - this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max); + this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max, false); } protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) { @@ -215,6 +223,7 @@ public class DoubleByte { return decodeBufferLoop(src, dst); } + @Override public int decode(byte[] src, int sp, int len, char[] dst) { int dp = 0; int sl = sp + len; @@ -230,12 +239,12 @@ public class DoubleByte { if (b2c[b1] == B2C_UNMAPPABLE || // isNotLeadingByte b2c[b2] != B2C_UNMAPPABLE || // isLeadingByte decodeSingle(b2) != UNMAPPABLE_DECODING) { - sp--; + sp--; } } } if (c == UNMAPPABLE_DECODING) { - c = repl; + c = repl; } } dst[dp++] = c; @@ -243,6 +252,11 @@ public class DoubleByte { return dp; } + @Override + public boolean isASCIICompatible() { + return isASCIICompatible; + } + public void implReset() { super.implReset(); } @@ -274,8 +288,14 @@ public class DoubleByte { private int currentState; public Decoder_EBCDIC(Charset cs, - char[][] b2c, char[] b2cSB, int b2Min, int b2Max) { - super(cs, b2c, b2cSB, b2Min, b2Max); + char[][] b2c, char[] b2cSB, int b2Min, int b2Max, + boolean isASCIICompatible) { + super(cs, b2c, b2cSB, b2Min, b2Max, isASCIICompatible); + } + + public Decoder_EBCDIC(Charset cs, + char[][] b2c, char[] b2cSB, int b2Min, int b2Max) { + super(cs, b2c, b2cSB, b2Min, b2Max, false); } public void implReset() { @@ -403,6 +423,7 @@ public class DoubleByte { } } + @Override public int decode(byte[] src, int sp, int len, char[] dst) { int dp = 0; int sl = sp + len; @@ -451,8 +472,13 @@ public class DoubleByte { b2cSB_UNMAPPABLE = new char[0x100]; Arrays.fill(b2cSB_UNMAPPABLE, UNMAPPABLE_DECODING); } + public Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max, + boolean isASCIICompatible) { + super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max, isASCIICompatible); + } + public Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) { - super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max); + super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max, false); } } @@ -464,8 +490,9 @@ public class DoubleByte { private final int SS3 = 0x8F; public Decoder_EUC_SIM(Charset cs, - char[][] b2c, char[] b2cSB, int b2Min, int b2Max) { - super(cs, b2c, b2cSB, b2Min, b2Max); + char[][] b2c, char[] b2cSB, int b2Min, int b2Max, + boolean isASCIICompatible) { + super(cs, b2c, b2cSB, b2Min, b2Max, isASCIICompatible); } // No support provided for G2/G3 for SimpleEUC @@ -481,6 +508,7 @@ public class DoubleByte { return CoderResult.unmappableForLength(2); } + @Override public int decode(byte[] src, int sp, int len, char[] dst) { int dp = 0; int sl = sp + len; @@ -515,17 +543,25 @@ public class DoubleByte { private final char[] c2b; private final char[] c2bIndex; protected Surrogate.Parser sgp; + final boolean isASCIICompatible; public Encoder(Charset cs, char[] c2b, char[] c2bIndex) { + this(cs, c2b, c2bIndex, false); + } + + public Encoder(Charset cs, char[] c2b, char[] c2bIndex, boolean isASCIICompatible) { super(cs, 2.0f, 2.0f); this.c2b = c2b; this.c2bIndex = c2bIndex; + this.isASCIICompatible = isASCIICompatible; } - public Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex) { + public Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex, + boolean isASCIICompatible) { super(cs, avg, max, repl); this.c2b = c2b; this.c2bIndex = c2bIndex; + this.isASCIICompatible = isASCIICompatible; } public boolean canEncode(char c) { @@ -624,6 +660,7 @@ public class DoubleByte { repl = newReplacement; } + @Override public int encode(char[] src, int sp, int len, byte[] dst) { int dp = 0; int sl = sp + len; @@ -647,11 +684,69 @@ public class DoubleByte { } else { // SingleByte dst[dp++] = (byte)bb; } + } + return dp; + } + + @Override + public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) { + int dp = 0; + int sl = sp + len; + while (sp < sl) { + char c = (char)(src[sp++] & 0xff); + int bb = encodeChar(c); + if (bb == UNMAPPABLE_ENCODING) { + // no surrogate pair in latin1 string + dst[dp++] = repl[0]; + if (repl.length > 1) { + dst[dp++] = repl[1]; + } + continue; + } //else + if (bb > MAX_SINGLEBYTE) { // DoubleByte + dst[dp++] = (byte)(bb >> 8); + dst[dp++] = (byte)bb; + } else { // SingleByte + dst[dp++] = (byte)bb; + } } return dp; } + @Override + public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) { + int dp = 0; + int sl = sp + len; + while (sp < sl) { + char c = StringUTF16.getChar(src, sp++); + int bb = encodeChar(c); + if (bb == UNMAPPABLE_ENCODING) { + if (Character.isHighSurrogate(c) && sp < sl && + Character.isLowSurrogate(StringUTF16.getChar(src, sp))) { + sp++; + } + dst[dp++] = repl[0]; + if (repl.length > 1) { + dst[dp++] = repl[1]; + } + continue; + } //else + if (bb > MAX_SINGLEBYTE) { // DoubleByte + dst[dp++] = (byte)(bb >> 8); + dst[dp++] = (byte)bb; + } else { // SingleByte + dst[dp++] = (byte)bb; + } + } + return dp; + } + + @Override + public boolean isASCIICompatible() { + return isASCIICompatible; + } + public int encodeChar(char ch) { return c2b[c2bIndex[ch >> 8] + (ch & 0xff)]; } @@ -741,9 +836,11 @@ public class DoubleByte { } public static class Encoder_DBCSONLY extends Encoder { + public Encoder_DBCSONLY(Charset cs, byte[] repl, - char[] c2b, char[] c2bIndex) { - super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex); + char[] c2b, char[] c2bIndex, + boolean isASCIICompatible) { + super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex, isASCIICompatible); } public int encodeChar(char ch) { @@ -754,8 +851,6 @@ public class DoubleByte { } } - - public static class Encoder_EBCDIC extends Encoder { static final int SBCS = 0; static final int DBCS = 1; @@ -764,8 +859,9 @@ public class DoubleByte { protected int currentState = SBCS; - public Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex) { - super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex); + public Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex, + boolean isASCIICompatible) { + super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex, isASCIICompatible); } protected void implReset() { @@ -878,6 +974,7 @@ public class DoubleByte { } } + @Override public int encode(char[] src, int sp, int len, byte[] dst) { int dp = 0; int sl = sp + len; @@ -917,12 +1014,88 @@ public class DoubleByte { } return dp; } + + @Override + public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) { + int dp = 0; + int sl = sp + len; + while (sp < sl) { + char c = (char)(src[sp++] & 0xff); + int bb = encodeChar(c); + if (bb == UNMAPPABLE_ENCODING) { + // no surrogate pair in latin1 string + dst[dp++] = repl[0]; + if (repl.length > 1) + dst[dp++] = repl[1]; + continue; + } //else + if (bb > MAX_SINGLEBYTE) { // DoubleByte + if (currentState == SBCS) { + currentState = DBCS; + dst[dp++] = SO; + } + dst[dp++] = (byte)(bb >> 8); + dst[dp++] = (byte)bb; + } else { // SingleByte + if (currentState == DBCS) { + currentState = SBCS; + dst[dp++] = SI; + } + dst[dp++] = (byte)bb; + } + } + if (currentState == DBCS) { + currentState = SBCS; + dst[dp++] = SI; + } + return dp; + } + + @Override + public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) { + int dp = 0; + int sl = sp + len; + while (sp < sl) { + char c = StringUTF16.getChar(src, sp++); + int bb = encodeChar(c); + if (bb == UNMAPPABLE_ENCODING) { + if (Character.isHighSurrogate(c) && sp < sl && + Character.isLowSurrogate(StringUTF16.getChar(src, sp))) { + sp++; + } + dst[dp++] = repl[0]; + if (repl.length > 1) + dst[dp++] = repl[1]; + continue; + } //else + if (bb > MAX_SINGLEBYTE) { // DoubleByte + if (currentState == SBCS) { + currentState = DBCS; + dst[dp++] = SO; + } + dst[dp++] = (byte)(bb >> 8); + dst[dp++] = (byte)bb; + } else { // SingleByte + if (currentState == DBCS) { + currentState = SBCS; + dst[dp++] = SI; + } + dst[dp++] = (byte)bb; + } + } + if (currentState == DBCS) { + currentState = SBCS; + dst[dp++] = SI; + } + return dp; + } } // EUC_SIMPLE public static class Encoder_EUC_SIM extends Encoder { - public Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex) { - super(cs, c2b, c2bIndex); + public Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex, + boolean isASCIICompatible) { + super(cs, c2b, c2bIndex, isASCIICompatible); } } diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java b/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java index 773c7a08a363f3feab0eb9ec1d06dc3cbab6fbd0..ed920e74adeccdbc1953cfc6a385923636246c7c 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java @@ -53,7 +53,7 @@ public class HKSCS { // super(cs, 0.5f, 1.0f); // need to extends DoubleByte.Decoder so the // sun.io can use it. this implementation - super(cs, 0.5f, 1.0f, null, null, 0, 0); + super(cs, 0.5f, 1.0f, null, null, 0, 0, true); this.big5Dec = big5Dec; this.b2cBmp = b2cBmp; this.b2cSupp = b2cSupp; @@ -239,7 +239,7 @@ public class HKSCS { char[][] c2bBmp, char[][] c2bSupp) { - super(cs, null, null); + super(cs, null, null, true); this.big5Enc = big5Enc; this.c2bBmp = c2bBmp; this.c2bSupp = c2bSupp; @@ -389,6 +389,33 @@ public class HKSCS { return dp; } + public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) { + int dp = 0; + int sl = sp + len; + int dl = dst.length; + while (sp < sl) { + char c = StringUTF16.getChar(src, sp++); + int bb = encodeChar(c); + if (bb == UNMAPPABLE_ENCODING) { + if (!Character.isHighSurrogate(c) || sp == sl || + !Character.isLowSurrogate(StringUTF16.getChar(src,sp)) || + (bb = encodeSupp(Character.toCodePoint(c, StringUTF16.getChar(src, sp++)))) + == UNMAPPABLE_ENCODING) { + dst[dp++] = repl[0]; + if (repl.length > 1) + dst[dp++] = repl[1]; + continue; + } + } + if (bb > MAX_SINGLEBYTE) { // DoubleByte + dst[dp++] = (byte)(bb >> 8); + dst[dp++] = (byte)bb; + } else { // SingleByte + dst[dp++] = (byte)bb; + } + } + return dp; + } static char[] C2B_UNMAPPABLE = new char[0x100]; static { diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java b/jdk/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java index 30181337173b811bdc0e744696f9ca289b61e03c..b5d93a8f6775dc8f95abb537732a2d35b791a3c6 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java @@ -132,6 +132,10 @@ class ISO_8859_1 dst[dp++] = (char)(src[sp++] & 0xff); return dp; } + + public boolean isASCIICompatible() { + return true; + } } private static class Encoder extends CharsetEncoder @@ -297,5 +301,9 @@ class ISO_8859_1 } return dp; } + + public boolean isASCIICompatible() { + return true; + } } } diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java b/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java index 6fd6faf331f51eb015bd6439a36ea1c3e5ca7f55..29a4246804da3bccf7d1e6b59040125fd4b13c88 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java @@ -49,10 +49,18 @@ public class SingleByte public static final class Decoder extends CharsetDecoder implements ArrayDecoder { private final char[] b2c; + private final boolean isASCIICompatible; public Decoder(Charset cs, char[] b2c) { super(cs, 1.0f, 1.0f); this.b2c = b2c; + this.isASCIICompatible = false; + } + + public Decoder(Charset cs, char[] b2c, boolean isASCIICompatible) { + super(cs, 1.0f, 1.0f); + this.b2c = b2c; + this.isASCIICompatible = isASCIICompatible; } private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) { @@ -116,6 +124,7 @@ public class SingleByte repl = newReplacement.charAt(0); } + @Override public int decode(byte[] src, int sp, int len, char[] dst) { if (len > dst.length) len = dst.length; @@ -129,6 +138,11 @@ public class SingleByte } return dp; } + + @Override + public boolean isASCIICompatible() { + return isASCIICompatible; + } } public static final class Encoder extends CharsetEncoder @@ -136,11 +150,13 @@ public class SingleByte private Surrogate.Parser sgp; private final char[] c2b; private final char[] c2bIndex; + private final boolean isASCIICompatible; - public Encoder(Charset cs, char[] c2b, char[] c2bIndex) { + public Encoder(Charset cs, char[] c2b, char[] c2bIndex, boolean isASCIICompatible) { super(cs, 1.0f, 1.0f); this.c2b = c2b; this.c2bIndex = c2bIndex; + this.isASCIICompatible = isASCIICompatible; } public boolean canEncode(char c) { @@ -252,6 +268,51 @@ public class SingleByte } return dp; } + + @Override + public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) { + int dp = 0; + int sl = sp + Math.min(len, dst.length); + while (sp < sl) { + char c = (char)(src[sp++] & 0xff); + int b = encode(c); + if (b == UNMAPPABLE_ENCODING) { + dst[dp++] = repl; + } else { + dst[dp++] = (byte)b; + } + } + return dp; + } + + @Override + public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) { + int dp = 0; + int sl = sp + Math.min(len, dst.length); + while (sp < sl) { + char c = StringUTF16.getChar(src, sp++); + int b = encode(c); + if (b != UNMAPPABLE_ENCODING) { + dst[dp++] = (byte)b; + continue; + } + if (Character.isHighSurrogate(c) && sp < sl && + Character.isLowSurrogate(StringUTF16.getChar(src, sp))) { + if (len > dst.length) { + sl++; + len--; + } + sp++; + } + dst[dp++] = repl; + } + return dp; + } + + @Override + public boolean isASCIICompatible() { + return isASCIICompatible; + } } // init the c2b and c2bIndex tables from b2c. diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/StringUTF16.java b/jdk/src/java.base/share/classes/sun/nio/cs/StringUTF16.java new file mode 100644 index 0000000000000000000000000000000000000000..f1608cab5d5f5c010b6e78b98d7f0e7107ef32d0 --- /dev/null +++ b/jdk/src/java.base/share/classes/sun/nio/cs/StringUTF16.java @@ -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. 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.cs; + +import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; +import static sun.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE; + +class StringUTF16 { + + public static char getChar(byte[] val, int index) { + return unsafe.getChar(val, + ARRAY_BYTE_BASE_OFFSET + ARRAY_BYTE_INDEX_SCALE * index * 2L); + } + + private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); +} diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/US_ASCII.java b/jdk/src/java.base/share/classes/sun/nio/cs/US_ASCII.java index 816a1ac439ff9ebd057daffeeb1715ae4ed50c62..39b7df07d8572d2fe22c997d1a0a37f4c9bbf98c 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/US_ASCII.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/US_ASCII.java @@ -146,6 +146,10 @@ public class US_ASCII } return dp; } + + public boolean isASCIICompatible() { + return true; + } } private static class Encoder extends CharsetEncoder @@ -259,6 +263,10 @@ public class US_ASCII } return dp; } + + public boolean isASCIICompatible() { + return true; + } } } diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/UTF_8.java b/jdk/src/java.base/share/classes/sun/nio/cs/UTF_8.java index 3ee2341f00023665aebc930b5b5d88d1827da5f1..06a434007457c5f1e9610d20c633cb5d79cc399e 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/UTF_8.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/UTF_8.java @@ -549,6 +549,10 @@ class UTF_8 extends Unicode } return dp; } + + public boolean isASCIICompatible() { + return true; + } } private static final class Encoder extends CharsetEncoder @@ -742,5 +746,9 @@ class UTF_8 extends Unicode } return dp; } + + public boolean isASCIICompatible() { + return true; + } } } diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/Cancellable.java b/jdk/src/java.base/share/classes/sun/nio/fs/Cancellable.java index 648d4089ce83a4178e16e8edf0033e3259d105c8..4e283a5f157609b2a6158970a621b49b30da813f 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/Cancellable.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/Cancellable.java @@ -26,7 +26,7 @@ package sun.nio.fs; import sun.misc.ManagedLocalsThread; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import java.util.concurrent.ExecutionException; /** diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java index 1009bda5de9d405dd1c1590ae187102d714e7b23..8acc0c198a1bbd0265ce0a098e0014b2bd5ba767 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java @@ -25,7 +25,7 @@ package sun.nio.fs; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.misc.Cleaner; /** diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java index 41ae7ea8835ebc4ef1d7858492b6c35c4214cc8f..728d96eb2b33959ecf141b84fc265866bb6dbb0b 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java @@ -25,7 +25,7 @@ package sun.nio.fs; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Factory for native buffers. diff --git a/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java b/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java index 96f64ec1847c90a60a4df31b252f4bf7aa40bca7..3b06f550f0f23d075f7874ceef0aead052b59876 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java +++ b/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java @@ -26,7 +26,7 @@ package sun.reflect; import java.lang.reflect.*; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** Shared functionality for all accessor generators */ diff --git a/jdk/src/java.base/share/classes/sun/reflect/ClassDefiner.java b/jdk/src/java.base/share/classes/sun/reflect/ClassDefiner.java index 6b1b43c841ba5f70af5fcc081a670b5a0f916a83..b4d50095939d337eb1a42c1e57c0307551ef52e9 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/ClassDefiner.java +++ b/jdk/src/java.base/share/classes/sun/reflect/ClassDefiner.java @@ -27,7 +27,7 @@ package sun.reflect; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** Utility class which assists in calling Unsafe.defineClass() by creating a new class loader which delegates to the one needed in diff --git a/jdk/src/java.base/share/classes/sun/reflect/FieldInfo.java b/jdk/src/java.base/share/classes/sun/reflect/FieldInfo.java index 6972155fb10bf5089a1e75c5289c53328fdbd639..72abd07b8619a610a72cc45576e6022ec1d94108 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/FieldInfo.java +++ b/jdk/src/java.base/share/classes/sun/reflect/FieldInfo.java @@ -38,7 +38,7 @@ public class FieldInfo { private String signature; private int modifiers; // This is compatible with the old reflection implementation's - // "slot" value to allow sun.misc.Unsafe to work + // "slot" value to allow jdk.internal.misc.Unsafe to work private int slot; // Not really necessary to provide a constructor since the VM diff --git a/jdk/src/java.base/share/classes/sun/reflect/MagicAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/MagicAccessorImpl.java index 59624366141fdcf8e187cbf6a79ce0c09155dc29..af1382f6a5e8bac0e996efd7fb91c814ffa6cdc2 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/MagicAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/MagicAccessorImpl.java @@ -32,7 +32,7 @@ package sun.reflect; fields and methods of other classes. It is used to hold the code for dynamically-generated FieldAccessorImpl and MethodAccessorImpl subclasses. (Use of the word "unsafe" was avoided in this class's - name to avoid confusion with {@link sun.misc.Unsafe}.) </P> + name to avoid confusion with {@link jdk.internal.misc.Unsafe}.) </P> <P> The bug fix for 4486457 also necessitated disabling verification for this class and all subclasses, as opposed to just diff --git a/jdk/src/java.base/share/classes/sun/reflect/ReflectionFactory.java b/jdk/src/java.base/share/classes/sun/reflect/ReflectionFactory.java index 354453311684bdda5443c432954323baa6fbf59a..24aa225b89ee47e01f7ff769669e179528db2697 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/ReflectionFactory.java +++ b/jdk/src/java.base/share/classes/sun/reflect/ReflectionFactory.java @@ -44,7 +44,7 @@ import sun.reflect.misc.ReflectUtil; subversion of both the language and the verifier. For this reason, they are all instance methods, and access to the constructor of this factory is guarded by a security check, in similar style to - {@link sun.misc.Unsafe}. </P> + {@link jdk.internal.misc.Unsafe}. </P> */ public class ReflectionFactory { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeFieldAccessorImpl.java index 8e830999f13a5d0af815b3e8f5657513ee55ed51..d54c7f8a6f62626699ca30bb2a9289e6221207b7 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeFieldAccessorImpl.java @@ -27,9 +27,9 @@ package sun.reflect; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; -/** Base class for sun.misc.Unsafe-based FieldAccessors. The +/** Base class for jdk.internal.misc.Unsafe-based FieldAccessors. The observation is that there are only nine types of fields from the standpoint of reflection code: the eight primitive types and Object. Using class Unsafe instead of generated bytecodes saves diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFieldAccessorImpl.java index a40ca9508810a4d11fbf1336be34035870a74c31..5cf6c5ee5c7d37ebf3d8d54c6a4ecb30f6df68ac 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFieldAccessorImpl.java @@ -27,10 +27,10 @@ package sun.reflect; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** - * Base class for sun.misc.Unsafe-based FieldAccessors for fields with + * Base class for jdk.internal.misc.Unsafe-based FieldAccessors for fields with * final or volatile qualifiers. These differ from unqualified * versions in that (1) they check for read-only status (2) they use * the volatile forms of Unsafe get/put methods. (When accessed via diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFieldAccessorImpl.java index 04219f1f49ccf92c51fd244608c81062c397908f..74b40571eaba514bc436f5467e5e2a6f14f577b0 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFieldAccessorImpl.java @@ -28,9 +28,9 @@ package sun.reflect; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.security.AccessController; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; -/** Base class for sun.misc.Unsafe-based FieldAccessors for final or +/** Base class for jdk.internal.misc.Unsafe-based FieldAccessors for final or static volatile fields. */ abstract class UnsafeQualifiedStaticFieldAccessorImpl diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFieldAccessorImpl.java index f07a17cdd5be3a1f36a458eb83679b57aa9202c0..e87ba31b5433b410b94fefbfd030c7d47445f780 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFieldAccessorImpl.java @@ -28,9 +28,9 @@ package sun.reflect; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.security.AccessController; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; -/** Base class for sun.misc.Unsafe-based FieldAccessors for static +/** Base class for jdk.internal.misc.Unsafe-based FieldAccessors for static fields. The observation is that there are only nine types of fields from the standpoint of reflection code: the eight primitive types and Object. Using class Unsafe instead of generated diff --git a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java index cee12a029eadd7333f3eecc5ab04aa393918df0a..c90a630e2fadd829084c8cb4da48714981e35da1 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java @@ -337,7 +337,7 @@ public final class ReflectUtil { /** * Checks if {@code Class cls} is a VM-anonymous class - * as defined by {@link sun.misc.Unsafe#defineAnonymousClass} + * as defined by {@link jdk.internal.misc.Unsafe#defineAnonymousClass} * (not to be confused with a Java Language anonymous inner class). */ public static boolean isVMAnonymousClass(Class<?> cls) { diff --git a/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java b/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java index e9e0b8f74ac2bf07edfd24c9b24764e65c377121..64f1c9da9fee9557a7f342ffbf2bc6428eccc46e 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java @@ -30,7 +30,7 @@ import static java.lang.Long.reverseBytes; import java.nio.ByteOrder; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Optimized methods for converting between byte[] and int[]/long[], both for diff --git a/jdk/src/java.base/share/native/libjava/String.c b/jdk/src/java.base/share/native/libjava/String.c index 7c8170ed3f894291fd4caeac32ee74c3b2ef2f25..cc7f740618f6e27cbdc5a2fee665b501d6c377ff 100644 --- a/jdk/src/java.base/share/native/libjava/String.c +++ b/jdk/src/java.base/share/native/libjava/String.c @@ -31,3 +31,14 @@ Java_java_lang_String_intern(JNIEnv *env, jobject this) { return JVM_InternString(env, this); } + +JNIEXPORT jboolean JNICALL +Java_java_lang_StringUTF16_isBigEndian(JNIEnv *env, jclass cls) +{ + unsigned int endianTest = 0xff000000; + if (((char*)(&endianTest))[0] != 0) { + return JNI_TRUE; + } else { + return JNI_FALSE; + } +} diff --git a/jdk/src/java.base/share/native/libjava/check_version.c b/jdk/src/java.base/share/native/libjava/check_version.c index b92bd63cdb4c37d7b357473b6b0bbc64075d314c..6d757a0b5f279e376bce08e4814f7072a4386e4a 100644 --- a/jdk/src/java.base/share/native/libjava/check_version.c +++ b/jdk/src/java.base/share/native/libjava/check_version.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 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 @@ -24,10 +24,11 @@ */ #include "jni.h" +#include "jni_util.h" #include "jvm.h" JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) +DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { jint vm_version = JVM_GetInterfaceVersion(); if (vm_version != JVM_INTERFACE_VERSION) { diff --git a/jdk/src/java.base/share/native/libjava/jio.c b/jdk/src/java.base/share/native/libjava/jio.c index 8a9cb44fe3e7a86686916aea0e56eaf8b6fa7786..efa327c2712445fd177ae6c4fa960edf91b046fb 100644 --- a/jdk/src/java.base/share/native/libjava/jio.c +++ b/jdk/src/java.base/share/native/libjava/jio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 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 @@ -27,6 +27,7 @@ #include "jni.h" +#ifndef STATIC_BUILD /* This is a temporary solution until we figure out how to let native * libraries use jio_* without linking with the VM. @@ -63,3 +64,6 @@ jio_fprintf(FILE *fp, const char *fmt, ...) return len; } + +#endif + diff --git a/jdk/src/java.base/share/native/libjava/jni_util.h b/jdk/src/java.base/share/native/libjava/jni_util.h index 0db1f1099c846498bce8f7091aeaed07e274ca89..96796571dc754bb1bb1e33911c06aba57db98a1a 100644 --- a/jdk/src/java.base/share/native/libjava/jni_util.h +++ b/jdk/src/java.base/share/native/libjava/jni_util.h @@ -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 @@ -389,6 +389,117 @@ void buildJniFunctionName(const char *sym, const char *cname, extern size_t getLastErrorString(char *buf, size_t len); extern int getErrorString(int err, char *buf, size_t len); + +#ifdef STATIC_BUILD +/* Macros for handling declaration of static/dynamic + * JNI library Load/Unload functions + * + * Use DEF_JNI_On{Un}Load when you want a static and non-static entry points. + * Use DEF_STATIC_JNI_On{Un}Load when you only want a static one. + * + * LIBRARY_NAME must be set to the name of the library + */ + +/* These three macros are needed to get proper concatenation of + * the LIBRARY_NAME + * + * NOTE: LIBRARY_NAME must be set for static builds. + */ +#define ADD_LIB_NAME3(name, lib) name ## lib +#define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib) +#define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME) + +#define DEF_JNI_OnLoad \ +ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) \ +{ \ + jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)(JavaVM *vm, void *reserved); \ + ADD_LIB_NAME(JNI_OnLoad_dynamic_)(vm, reserved); \ + return JNI_VERSION_1_8; \ +} \ +jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_) + +#define DEF_STATIC_JNI_OnLoad \ +JNIEXPORT jint JNICALL ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) { \ + return JNI_VERSION_1_8; \ +} + +#define DEF_JNI_OnUnload \ +ADD_LIB_NAME(JNI_OnUnload_)(JavaVM *vm, void *reserved) \ +{ \ + void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)(JavaVM *vm, void *reserved); \ + ADD_LIB_NAME(JNI_OnUnload_dynamic_)(vm, reserved); \ +} \ +void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_) + +#define DEF_STATIC_JNI_OnUnload \ +ADD_LIB_NAME(JNI_OnUnload_) + +#else + +#define DEF_JNI_OnLoad JNI_OnLoad +#define DEF_STATIC_JNI_OnLoad +#define DEF_JNI_OnUnload JNI_OnUnload +#define DEF_STATIC_JNI_OnUnload +#endif + +#ifdef STATIC_BUILD +/* Macros for handling declaration of static/dynamic + * Agent library Load/Attach/Unload functions + * + * Use DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload + * when you want both static and non-static entry points. + * Use DEF_STATIC_Agent_OnLoad, DEF_STATIC_Agent_OnAttach or + * DEF_STATIC_Agent_OnUnload when you only want a static one. + * + * LIBRARY_NAME must be set to the name of the library for static builds. + */ + +#define DEF_Agent_OnLoad \ +ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \ +{ \ + jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \ + return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \ +} \ +jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_) + +#define DEF_STATIC_Agent_OnLoad \ +JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \ + return JNI_FALSE; \ +} + +#define DEF_Agent_OnAttach \ +ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \ +{ \ + jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \ + return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \ +} \ +jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_) + +#define DEF_STATIC_Agent_OnAttach \ +JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \ + return JNI_FALSE; \ +} + +#define DEF_Agent_OnUnload \ +ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \ +{ \ + void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \ + ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \ +} \ +void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_) + +#define DEF_STATIC_Agent_OnUnload \ +ADD_LIB_NAME(Agent_OnUnload_) + +#else +#define DEF_Agent_OnLoad Agent_OnLoad +#define DEF_Agent_OnAttach Agent_OnAttach +#define DEF_Agent_OnUnload Agent_OnUnload +#define DEF_STATIC_Agent_OnLoad +#define DEF_STATIC_Agent_OnAttach +#define DEF_STATIC_Agent_OnUnload +#endif + #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ diff --git a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp index 0f803cb4fa949e7a3877ff0afb2fac6c8b9d83f9..2528c5850f4aa45295efe88653983b394bed606c 100644 --- a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp +++ b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp @@ -26,6 +26,7 @@ #include <string.h> #include "jni.h" +#include "jni_util.h" #include "endian.hpp" #include "imageDecompressor.hpp" @@ -246,7 +247,7 @@ static unsigned int JIMAGE_AttributeOffsetsLength(JNIEnv *env, jlong id) { } JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) { +DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; if (vm->GetEnv((void**) &env, JNI_VERSION_1_2) != JNI_OK) { @@ -646,6 +647,6 @@ JNIEXPORT jstring JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1 return module; } -JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { +JNIEXPORT void JNICALL DEF_JNI_OnUnload(JavaVM *vm, void *reserved) { ImageDecompressor::image_decompressor_close(); } diff --git a/jdk/src/java.base/share/native/libjimage/imageFile.cpp b/jdk/src/java.base/share/native/libjimage/imageFile.cpp index 1e067f2cdd4663c59ab3c77b964e6d283b5baeec..9b4e031b35809ff661e58edfacf91d645e6f1ab8 100644 --- a/jdk/src/java.base/share/native/libjimage/imageFile.cpp +++ b/jdk/src/java.base/share/native/libjimage/imageFile.cpp @@ -118,7 +118,7 @@ void ImageLocation::set_data(u1* data) { // Deflate the attribute stream into an array of attributes. u1 byte; // Repeat until end header is found. - while ((byte = *data)) { + while ((data != NULL) && (byte = *data)) { // Extract kind from header byte. u1 kind = attribute_kind(byte); assert(kind < ATTRIBUTE_COUNT && "invalid image location attribute"); @@ -191,7 +191,7 @@ ImageModuleData::ImageModuleData(const ImageFileReader* image_file, // Release module data resource. ImageModuleData::~ImageModuleData() { if (_data) { - delete _data; + delete[] _data; } } @@ -274,7 +274,7 @@ ImageFileReaderTable::ImageFileReaderTable() : _count(0), _max(_growth) { } ImageFileReaderTable::~ImageFileReaderTable() { - delete _table; + delete[] _table; } // Add a new image entry to the table. @@ -414,7 +414,7 @@ ImageFileReader::~ImageFileReader() { close(); // Free up name. if (_name) { - delete _name; + delete[] _name; _name = NULL; } } @@ -668,7 +668,7 @@ void ImageFileReader::get_resource(ImageLocation& location, u1* uncompressed_dat &strings); // If not memory mapped then release temporary buffer. if (!MemoryMapImage) { - delete compressed_data; + delete[] compressed_data; } } else { // Read bytes from offset beyond the image index. diff --git a/jdk/src/java.base/share/native/libnet/net_util.c b/jdk/src/java.base/share/native/libnet/net_util.c index 9bdbad33baa16b47aa2752f4b0e8541f78a95ede..e94903fd720e3269effd7011ff3a5fd836007e57 100644 --- a/jdk/src/java.base/share/native/libnet/net_util.c +++ b/jdk/src/java.base/share/native/libnet/net_util.c @@ -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 @@ -38,7 +38,7 @@ JNIEXPORT jint JNICALL ipv6_available() } JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) +DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; jclass iCls; diff --git a/jdk/src/java.base/share/native/libnio/nio_util.c b/jdk/src/java.base/share/native/libnio/nio_util.c index f61c65268e881cb5333a0ff1fe8316d399a46d3d..2235f0a5998da9514de9e935788a1c17a149c012 100644 --- a/jdk/src/java.base/share/native/libnio/nio_util.c +++ b/jdk/src/java.base/share/native/libnio/nio_util.c @@ -28,7 +28,7 @@ #include "jni_util.h" JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) +DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; diff --git a/jdk/src/java.base/share/native/libverify/check_code.c b/jdk/src/java.base/share/native/libverify/check_code.c index 0391b3664377906f3e25a99fc09d26747da3e40d..e22101496d7380a0c094e5cf37001adee37f01b6 100644 --- a/jdk/src/java.base/share/native/libverify/check_code.c +++ b/jdk/src/java.base/share/native/libverify/check_code.c @@ -86,6 +86,7 @@ #include <stdlib.h> #include "jni.h" +#include "jni_util.h" #include "jvm.h" #include "classfile_constants.h" #include "opcodes.in_out" @@ -481,6 +482,11 @@ static void print_formatted_fieldname(context_type *context, int index); static void print_formatted_methodname(context_type *context, int index); #endif +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + void initialize_class_hash(context_type *context) { hash_table_type *class_hash = &(context->class_hash); diff --git a/jdk/src/java.base/share/native/libzip/ZipFile.c b/jdk/src/java.base/share/native/libzip/ZipFile.c index 51c4f77195c963714bed2e0ac567c79a8b580900..d7a21a6cf887ea680baf626e692057c5d25d2cc1 100644 --- a/jdk/src/java.base/share/native/libzip/ZipFile.c +++ b/jdk/src/java.base/share/native/libzip/ZipFile.c @@ -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 @@ -55,6 +55,12 @@ static jfieldID jzfileID; static int OPEN_READ = java_util_zip_ZipFile_OPEN_READ; static int OPEN_DELETE = java_util_zip_ZipFile_OPEN_DELETE; + +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + JNIEXPORT void JNICALL Java_java_util_zip_ZipFile_initIDs(JNIEnv *env, jclass cls) { diff --git a/jdk/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java b/jdk/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java index 5355f7f29119c99d31790118383dc3955ef57e9b..30a454c070fdd959f896fd44392787bdd24d66c2 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java @@ -31,7 +31,7 @@ import java.util.BitSet; import java.util.HashMap; import java.util.Map; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.security.action.GetIntegerAction; import static sun.nio.ch.SolarisEventPort.*; diff --git a/jdk/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java b/jdk/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java index f5427d6fb7ac15ee000fe4e4c4d44478f711abea..298727dccd4ae4cca79bee177bb29326ad0b86ef 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java @@ -28,7 +28,7 @@ package sun.nio.ch; import java.nio.channels.spi.AsynchronousChannelProvider; import java.util.concurrent.RejectedExecutionException; import java.io.IOException; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Provides an AsynchronousChannelGroup implementation based on the Solaris 10 diff --git a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java index f3ba7b3e6f0730aa32e8fb6f46117040b5c0ed6a..7027bd96c2a484f18862685f9314ba26ae866626 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java @@ -29,7 +29,7 @@ import java.nio.file.*; import java.nio.file.attribute.*; import java.util.*; import java.io.IOException; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.SolarisConstants.*; diff --git a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java index 0c1165ff5f43f8cb99ca963755d52b6c2096c5c2..7a31d13b3a643b8c85212972110a9c6502f1e9f0 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java @@ -30,7 +30,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import java.io.IOException; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static sun.nio.fs.UnixConstants.*; diff --git a/jdk/src/java.base/unix/native/libjava/jlong_md.h b/jdk/src/java.base/unix/native/libjava/jlong_md.h index 97b08e69a5ae355492961cd75563b4920d4f4adb..40fb0af5496d64516fa40dbb68c73ab494925f8b 100644 --- a/jdk/src/java.base/unix/native/libjava/jlong_md.h +++ b/jdk/src/java.base/unix/native/libjava/jlong_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, 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 @@ -65,11 +65,19 @@ #define jlong_zero_init ((jlong) 0L) #ifdef _LP64 -#define jlong_to_ptr(a) ((void*)(a)) -#define ptr_to_jlong(a) ((jlong)(a)) + #ifndef jlong_to_ptr + #define jlong_to_ptr(a) ((void*)(a)) + #endif + #ifndef ptr_to_jlong + #define ptr_to_jlong(a) ((jlong)(a)) + #endif #else -#define jlong_to_ptr(a) ((void*)(int)(a)) -#define ptr_to_jlong(a) ((jlong)(int)(a)) + #ifndef jlong_to_ptr + #define jlong_to_ptr(a) ((void*)(int)(a)) + #endif + #ifndef ptr_to_jlong + #define ptr_to_jlong(a) ((jlong)(int)(a)) + #endif #endif #define jint_to_jlong(a) ((jlong)(a)) diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/Iocp.java b/jdk/src/java.base/windows/classes/sun/nio/ch/Iocp.java index 699df0500309d5ab3cb03c6f6019daad076a4709..715046a0ede30ad500495ceae7db57a5b4f0766b 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/ch/Iocp.java +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/Iocp.java @@ -36,7 +36,7 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.security.AccessController; import sun.security.action.GetPropertyAction; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Windows implementation of AsynchronousChannelGroup encapsulating an I/O diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/PendingIoCache.java b/jdk/src/java.base/windows/classes/sun/nio/ch/PendingIoCache.java index 72d8d0ea9d96e799d3e2b3255566a91eacbd4986..b8f7cba96f367306cee4e481ac18da4a93e1fc79 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/ch/PendingIoCache.java +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/PendingIoCache.java @@ -27,7 +27,7 @@ package sun.nio.ch; import java.nio.channels.*; import java.util.*; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Maintains a mapping of pending I/O requests (identified by the address of diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java index 991944e96c747f4f0e647605695607b8a8a480ea..9d5945364b936748d229a3ea82ad8bcc33049f3b 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java @@ -33,7 +33,7 @@ import java.io.IOException; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Windows implementation of AsynchronousServerSocketChannel using overlapped I/O. diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java index 1880548f68f56dda38626884b1417af06f189db6..3e96279de41ce70f56db769f87c24b46cfd93938 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java @@ -34,7 +34,7 @@ import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Windows implementation of AsynchronousSocketChannel using overlapped I/O. diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java index 208435dc97e1baffe12d34be8d782d1f2d11ba83..02226053f8d4188c6618d299d3b86d9debaccfa9 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java @@ -28,7 +28,7 @@ package sun.nio.fs; import java.nio.file.attribute.*; import java.util.concurrent.TimeUnit; import java.security.AccessController; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; import static sun.nio.fs.WindowsNativeDispatcher.*; diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java index e86c385a622f9e7cb2b96853c4e3b9e33fd6ac6f..cf0d23fea2b96768466a248a82b9576b16f43c34 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java @@ -33,7 +33,7 @@ import java.util.concurrent.ExecutorService; import java.io.*; import java.util.*; import java.security.AccessController; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.nio.ch.ThreadPool; import sun.security.util.SecurityConstants; diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java index 56f996d99b32d74ccab0cbd270c2953784315407..80d4809b6a5810fdb9cf6c188119e87d761f16f6 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java @@ -30,7 +30,7 @@ import java.io.IOException; import java.io.IOError; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static sun.nio.fs.WindowsNativeDispatcher.*; import static sun.nio.fs.WindowsConstants.*; diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java index 82a4bc3aecdec475e3e25a137d2dd676f0590c60..820edbfd9a89803bae4e149a8d9c3b06edd5b99c 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java @@ -27,7 +27,7 @@ package sun.nio.fs; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Win32 and library calls. diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java index fb432271cc68b0be6bcfc32a3209a999c90dec85..da3460592f49854117b700e6eefeb864f7d37441 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java @@ -29,7 +29,7 @@ import java.nio.file.ProviderMismatchException; import java.nio.file.attribute.*; import java.util.*; import java.io.IOException; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static sun.nio.fs.WindowsNativeDispatcher.*; import static sun.nio.fs.WindowsConstants.*; diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java index 64ef12a9855552524250f45338de7b5b9c818d44..774d248840c78a21152c07c627f53feff952b027 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java @@ -31,7 +31,7 @@ import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.io.IOException; import java.util.*; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static sun.nio.fs.WindowsNativeDispatcher.*; import static sun.nio.fs.WindowsConstants.*; diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java index 0ea288e1ecb6ae10e7c61247c126c1120d80761f..8e28e8471ac2625afd787d813f7f8ec1b9ec2c03 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java @@ -36,7 +36,7 @@ import java.util.Map; import java.util.Set; import com.sun.nio.file.ExtendedWatchEventModifier; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import static sun.nio.fs.WindowsNativeDispatcher.*; import static sun.nio.fs.WindowsConstants.*; diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m index 1a048057ea166f89a98b01688dcdbf24ecec082c..8f1e269de8f45520156f477c375f41c183d471c5 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m @@ -740,7 +740,7 @@ Java_sun_lwawt_macosx_LWCToolkit_initAppkit JNF_COCOA_EXIT(env) } -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { +JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { OSXAPP_SetJavaVM(vm); // We need to let Foundation know that this is a multithreaded application, if it isn't already. diff --git a/jdk/src/java.desktop/macosx/native/libjawt/jawt.m b/jdk/src/java.desktop/macosx/native/libjawt/jawt.m index e737facf9b43671b185f54b625fcee23287f1cb0..cd9f52a8e5ef45f0469cb78a9c55190f3b5ae437 100644 --- a/jdk/src/java.desktop/macosx/native/libjawt/jawt.m +++ b/jdk/src/java.desktop/macosx/native/libjawt/jawt.m @@ -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 @@ -24,11 +24,17 @@ */ #import <jawt.h> +#import "jni_util.h" #import <jawt_md.h> #import "awt_DrawingSurface.h" +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /* * Get the AWT native structure. * This function returns JNI_FALSE if an error occurs. diff --git a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h index 69d380032dfed00f382a50f610d4013e4043daeb..c84ad06f9b5c31cd53900cc5f351e72d1077c9a5 100644 --- a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h +++ b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h @@ -23,6 +23,12 @@ * questions. */ +/* + * Must include this before JavaNativeFoundation.h to get jni.h from build + */ +#include "jni.h" +#include "jni_util.h" + #import <Cocoa/Cocoa.h> #import <JavaNativeFoundation/JavaNativeFoundation.h> diff --git a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m index 8a856bdabdd9386ba53ca2c04c225f2690a43249..579056f7117e9fc68991ed8322379e57e64db198 100644 --- a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m +++ b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m @@ -33,6 +33,10 @@ #import "QueuingApplicationDelegate.h" #import "AWTIconData.h" +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad static BOOL sUsingDefaultNIB = YES; static NSString *SHARED_FRAMEWORK_BUNDLE = @"/System/Library/Frameworks/JavaVM.framework"; @@ -432,10 +436,10 @@ AWT_ASSERT_APPKIT_THREAD; @end -void OSXAPP_SetApplicationDelegate(id <NSApplicationDelegate> delegate) +void OSXAPP_SetApplicationDelegate(id <NSApplicationDelegate> newdelegate) { AWT_ASSERT_APPKIT_THREAD; - applicationDelegate = delegate; + applicationDelegate = newdelegate; if (NSApp != nil) { [NSApp setDelegate: applicationDelegate]; diff --git a/jdk/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m b/jdk/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m index cf58d7599c0175239c0854adce9907d3f9a63643..50ac4ba51e2220aa356c36b8e7e641f456cfb9f4 100644 --- a/jdk/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m +++ b/jdk/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, 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,10 @@ * questions. */ +// Must include this before JavaNativeFoundation.h to get jni.h from build +#include "jni.h" +#include "jni_util.h" + #import <JavaNativeFoundation/JavaNativeFoundation.h> /* @@ -30,6 +34,7 @@ * <rdar://4984599> AWT's JNI_OnLoad called multiple times * Please remove when <rdar://5121166> has been resolved. */ -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { +JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) +{ return JNI_VERSION_1_4; } diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java index e9afc44069e96cbee563b45cc81ff689a6bfc9af..a025ae85e5f07068ccff1cd734f980503843fb90 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java @@ -25,7 +25,7 @@ package sun.awt; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import javax.accessibility.AccessibleContext; import java.awt.*; diff --git a/jdk/src/java.desktop/share/classes/sun/font/StrikeCache.java b/jdk/src/java.desktop/share/classes/sun/font/StrikeCache.java index 99319c7d16ab9856d2d023db17d561ff3400a612..094327fe124d66313aba487db3fdd8bc13d9f5b0 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/StrikeCache.java +++ b/jdk/src/java.desktop/share/classes/sun/font/StrikeCache.java @@ -37,7 +37,7 @@ import sun.java2d.Disposer; import sun.java2d.pipe.BufferedContext; import sun.java2d.pipe.RenderQueue; import sun.java2d.pipe.hw.AccelGraphicsConfig; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java index 5f5118a8767dd118823da4e23d68b9e7bac6677b..57f24a4eadafb5f92e9193356fd7152d527cd4b4 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java @@ -25,7 +25,7 @@ package sun.java2d.pipe; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** diff --git a/jdk/src/java.desktop/share/classes/sun/swing/SwingAccessor.java b/jdk/src/java.desktop/share/classes/sun/swing/SwingAccessor.java index da637f0625c49d816ec5aafacfe8730dc73c6aff..66d20f2458b190f2dd0d38a06075e5780e5105b4 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/SwingAccessor.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/SwingAccessor.java @@ -25,7 +25,7 @@ package sun.swing; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import java.awt.*; import javax.swing.*; diff --git a/jdk/src/java.desktop/share/native/libfontmanager/sunFont.c b/jdk/src/java.desktop/share/native/libfontmanager/sunFont.c index 0695088899bd22debfe6d49e61e5e02bfc7fd578..866752f99d125af4488fbddfddd46fb6ba8fc697 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/sunFont.c +++ b/jdk/src/java.desktop/share/native/libfontmanager/sunFont.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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,6 +37,10 @@ static void *theNullScalerContext = NULL; extern void AccelGlyphCache_RemoveAllCellInfos(GlyphInfo *glyph); +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad JNIEXPORT jlong JNICALL Java_sun_font_NullFontScaler_getNullScalerContext diff --git a/jdk/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c b/jdk/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c index 37b743a03399dbc8392248ae77db4ba6f47a4976..65ef089a06a23367e71eb6966df60812024c42f4 100644 --- a/jdk/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c +++ b/jdk/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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,7 +67,7 @@ static jmethodID InputStream_availableID; JavaVM *jvm; JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) +DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { jvm = vm; return JNI_VERSION_1_2; diff --git a/jdk/src/java.desktop/share/native/libjsound/Platform.c b/jdk/src/java.desktop/share/native/libjsound/Platform.c index 9533bd8bbf74ab280c70ce76868aade8fd7e5c09..6933920ec59729386bcee5779711d4b3ae80a900 100644 --- a/jdk/src/java.desktop/share/native/libjsound/Platform.c +++ b/jdk/src/java.desktop/share/native/libjsound/Platform.c @@ -28,6 +28,10 @@ // Platform.java includes #include "com_sun_media_sound_Platform.h" +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad /* * Class: com_sun_media_sound_Platform diff --git a/jdk/src/java.desktop/share/native/libjsound/Utilities.h b/jdk/src/java.desktop/share/native/libjsound/Utilities.h index 3f05a9ff1711da8eba7e99952d02aacb7222fb76..fbecab1e005cbbc06116386feac104c24ae3a1b1 100644 --- a/jdk/src/java.desktop/share/native/libjsound/Utilities.h +++ b/jdk/src/java.desktop/share/native/libjsound/Utilities.h @@ -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 @@ -24,6 +24,7 @@ */ #include <jni.h> +#include "jni_util.h" #include "SoundDefs.h" #include "Configure.h" // put flags for debug msgs etc. here diff --git a/jdk/src/java.desktop/share/native/liblcms/LCMS.c b/jdk/src/java.desktop/share/native/liblcms/LCMS.c index 4391c4b8ef18a10b37e0af9ba67014c9b3fc539d..97dc17593ed725bde9e92d458ee5672a757d4ef2 100644 --- a/jdk/src/java.desktop/share/native/liblcms/LCMS.c +++ b/jdk/src/java.desktop/share/native/liblcms/LCMS.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -134,7 +134,7 @@ void errorHandler(cmsContext ContextID, cmsUInt32Number errorCode, JNU_ThrowByName(env, "java/awt/color/CMMException", errMsg); } -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { +JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *jvm, void *reserved) { javaVM = jvm; cmsSetLogErrorHandler(errorHandler); diff --git a/jdk/src/java.desktop/share/native/libmlib_image/mlib_ImageUtils.c b/jdk/src/java.desktop/share/native/libmlib_image/mlib_ImageUtils.c index eabe9e67af46d270e5aac5540b198f47648439e1..91481a4d99750d6fb0b81b400bc165c66baae2fb 100644 --- a/jdk/src/java.desktop/share/native/libmlib_image/mlib_ImageUtils.c +++ b/jdk/src/java.desktop/share/native/libmlib_image/mlib_ImageUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, 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 @@ -26,6 +26,14 @@ #include "mlib_image.h" +#include <jni.h> +#include "jni_util.h" + +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /***************************************************************/ typedef union { mlib_d64 db; diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c b/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c index 53aae4f97b6ed491d8b23e73eb11df1fa988923c..02c4a164fc15c8e696edce5192f502cb661187f3 100644 --- a/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c +++ b/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c @@ -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 <sizecalc.h> JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM * vm, void *reserved) +DEF_JNI_OnLoad(JavaVM * vm, void *reserved) { return JNI_VERSION_1_2; } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDConstants.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDConstants.java index 26e2cdbbba32e3ef988ad99f799242070426a85c..f2dbfc67abf294c9966df03c6cf645f52935c4ec 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDConstants.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDConstants.java @@ -31,7 +31,7 @@ import java.nio.ByteOrder; import java.util.Arrays; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Motif DnD protocol global constants and convenience routines. diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java index da80dda9ceb00ccb9dd92f4bf1dbfb5ec6b685b2..a476628e7c56ab9d4dab02e1520ec36ca2c2f897 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java @@ -33,7 +33,7 @@ import java.awt.dnd.InvalidDnDOperationException; import java.util.Map; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * XDragSourceProtocol implementation for Motif DnD protocol. diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java index 735bf144df2bcc411a21af370fff24aeea1dd840..e71236a6ff97aa8cb6197c8781b15b0066f18bd8 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java @@ -33,7 +33,7 @@ import java.awt.event.MouseEvent; import java.io.IOException; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * XDropTargetProtocol implementation for Motif DnD protocol. diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java index f61654643f26e8cc4788db0a8e807d6eb4c58b7c..e4d5b23ca76c015e10e3628611c7f374dfaac3ae 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java @@ -25,7 +25,7 @@ package sun.awt.X11; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import java.util.Vector; import java.security.AccessController; import java.security.PrivilegedAction; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/UnsafeXDisposerRecord.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/UnsafeXDisposerRecord.java index 099b558eef6295ff1fb776dab3ea499f6a6673a5..6de0c0310ef4e27e351d21c37d386eea9a594ce6 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/UnsafeXDisposerRecord.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/UnsafeXDisposerRecord.java @@ -24,7 +24,7 @@ */ package sun.awt.X11; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.util.logging.PlatformLogger; class UnsafeXDisposerRecord implements sun.java2d.DisposerRecord { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/WindowPropertyGetter.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/WindowPropertyGetter.java index 0cda6fa2fdfd55e785755af4564216b54bcbeeb6..00d3134eea86145e99d533c3c7c622c0f545c4a8 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/WindowPropertyGetter.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/WindowPropertyGetter.java @@ -26,7 +26,7 @@ package sun.awt.X11; import java.util.*; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; public class WindowPropertyGetter { private static Unsafe unsafe = XlibWrapper.unsafe; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java index 01d17fdad213a7c9589ef65d988b1c1dc93397e9..eeb46347b569744e691ee1adfe2e17901eadf645 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java @@ -55,7 +55,7 @@ package sun.awt.X11; * @since 1.5 */ -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import java.util.HashMap; public final class XAtom { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java index a4661e5c6872956858d706f3dfa38e002c5606e1..26265be30bcac877202a2de08e3d49389c9d43a9 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java @@ -35,7 +35,7 @@ import java.util.Map; import sun.util.logging.PlatformLogger; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * XDragSourceProtocol implementation for XDnD protocol. diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java index 074f37dd753786cb4ed739df0ded61189f53c8c9..e1698a424b844178cee6d01a0cef394c564849fa 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java @@ -35,7 +35,7 @@ import java.io.IOException; import sun.util.logging.PlatformLogger; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * XDropTargetProtocol implementation for XDnD protocol. diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDropTargetContextPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDropTargetContextPeer.java index 1e59ce16e82aabf7bab52b305f5dbcd24a64f703..d2a6c9f8c04b51a1590dec3fecda7a677fe15d3e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDropTargetContextPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDropTargetContextPeer.java @@ -41,7 +41,7 @@ import sun.awt.SunToolkit; import sun.awt.dnd.SunDropTargetContextPeer; import sun.awt.dnd.SunDropTargetEvent; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * The XDropTargetContextPeer is the class responsible for handling diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedHelper.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedHelper.java index f54f4bd9e6610bb63037bf7613a2b65079131848..0c2acc44c1cd3161e5d7ea535c8ec295029a884d 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedHelper.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedHelper.java @@ -25,7 +25,7 @@ package sun.awt.X11; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.util.logging.PlatformLogger; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeysym.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeysym.java index b0b0d0728ed58e91ce24094b58922d2aef3a8210..e34298a13e794454a6c03a0167d47dc8093c5615 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeysym.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeysym.java @@ -27,7 +27,7 @@ package sun.awt.X11; import java.util.Hashtable; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.util.logging.PlatformLogger; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XQueryTree.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XQueryTree.java index dede21f6e3065473a3fac9b5dcc94a62534a4d49..7c3641d4c4283085c4c72cd24a05462c71063e0c 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XQueryTree.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XQueryTree.java @@ -27,7 +27,7 @@ package sun.awt.X11; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; public class XQueryTree { private static Unsafe unsafe = XlibWrapper.unsafe; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTranslateCoordinates.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTranslateCoordinates.java index 42a3a42844e8cf0292fc803e6948e57d7ca072d9..bc08e2077dde9474d5a2d07b11e21db3c0077800 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTranslateCoordinates.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTranslateCoordinates.java @@ -27,7 +27,7 @@ package sun.awt.X11; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; public class XTranslateCoordinates { private static Unsafe unsafe = XlibWrapper.unsafe; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java index 61d2cbc380deaa297c8f27139b28598b4e8ec760..9fce6afe2847c773792d3cc1df12665fc72b9d2d 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java @@ -31,7 +31,7 @@ package sun.awt.X11; import sun.awt.IconInfo; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import java.awt.Insets; import java.awt.Frame; import java.awt.Rectangle; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java index bc9e3667a1fc2118b8b464c83d3c3871ca6f32f8..9edec019bb444c444153bbabd187f796267753ad 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java @@ -27,7 +27,7 @@ package sun.awt.X11; import java.security.AccessController; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; final class XlibWrapper { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/keysym2ucs.h b/jdk/src/java.desktop/unix/classes/sun/awt/X11/keysym2ucs.h index 09de3bee0989adbdd985b4b918e8e9804d71013e..b0c75b313fac85b5b1611686a0bc4388f76bb330 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/keysym2ucs.h +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/keysym2ucs.h @@ -65,7 +65,7 @@ tojava */ tojava tojava package sun.awt.X11; tojava import java.util.Hashtable; -tojava import sun.misc.Unsafe; +tojava import jdk.internal.misc.Unsafe; tojava tojava import sun.util.logging.PlatformLogger; tojava diff --git a/jdk/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c b/jdk/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c index 3f79aa36c79ebdbcae00b9d12f83a1f717f4726b..55fbd2324e37256f8f243aae498bef424f159bd9 100644 --- a/jdk/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c +++ b/jdk/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c @@ -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 @@ -178,7 +178,7 @@ AWT_OnLoad(JavaVM *vm, void *reserved) } JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) +DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { return AWT_OnLoad(vm, reserved); } diff --git a/jdk/src/java.desktop/unix/native/libawt_headless/awt/HeadlessToolkit.c b/jdk/src/java.desktop/unix/native/libawt_headless/awt/HeadlessToolkit.c index fd17f3b87f251d5737e0e2e41185fa6b0eb669f7..8aa34f4967b2c8093182db93ef17c82bd7e785da 100644 --- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/HeadlessToolkit.c +++ b/jdk/src/java.desktop/unix/native/libawt_headless/awt/HeadlessToolkit.c @@ -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 @@ -31,14 +31,17 @@ extern JavaVM *jvm; JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) +DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { jvm = vm; return JNI_VERSION_1_2; } +#ifndef STATIC_BUILD +// The same function exists in libawt.a::awt_LoadLibrary.c JNIEXPORT jboolean JNICALL AWTIsHeadless() { return JNI_TRUE; } +#endif #endif diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c index 2e96cc843c69188c0c078be195e91e925fdef310..3b340914658ff40c90170bac52d7299ad8e16606 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c @@ -151,7 +151,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XToolkit_getDefaultScreenData JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) +DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { jvm = vm; return JNI_VERSION_1_2; diff --git a/jdk/src/java.desktop/unix/native/libjawt/jawt.c b/jdk/src/java.desktop/unix/native/libjawt/jawt.c index 64284bc6e9eaf5a2d101ac640301698f6d67f9a3..1b7c0499258789ad4b5ed79164a1a68a20baa1f9 100644 --- a/jdk/src/java.desktop/unix/native/libjawt/jawt.c +++ b/jdk/src/java.desktop/unix/native/libjawt/jawt.c @@ -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 @@ -24,9 +24,15 @@ */ #include <jawt.h> +#include "jni_util.h" #include "awt_DrawingSurface.h" +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /* * Get the AWT native structure. This function returns JNI_FALSE if * an error occurs. diff --git a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c index cc91adb850ca9f1285a45ca272698d705cb6ace4..230be0c7c8fa118f139772d97198aede948e736a 100644 --- a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c +++ b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -44,6 +44,11 @@ static int alsa_inited = 0; static int alsa_enumerate_pcm_subdevices = FALSE; // default: no static int alsa_enumerate_midi_subdevices = FALSE; // default: no +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + void initAlsaSupport() { char* enumerate; if (!alsa_inited) { diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index dcb4ea71f8db4b0262a737f56b73189c0d9e91cf..412e45a5c593df1d5e1c5ffb9bec9d25b77e56bf 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, 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 @@ extern void DWMResetCompositionEnabled(); JavaVM *jvm = NULL; JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) +DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { TRY; diff --git a/jdk/src/java.desktop/windows/native/libjawt/jawt.cpp b/jdk/src/java.desktop/windows/native/libjawt/jawt.cpp index 9c33b0238bbd678315d84872a5d6ba2f93eba690..218b7dd0864908349a94dd038befbc62c50ef615 100644 --- a/jdk/src/java.desktop/windows/native/libjawt/jawt.cpp +++ b/jdk/src/java.desktop/windows/native/libjawt/jawt.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, 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 @@ -25,10 +25,16 @@ #define _JNI_IMPLEMENTATION_ #include <jawt.h> +#include "jni_util.h" #include "awt.h" #include "awt_DrawingSurface.h" +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /* * Get the AWT native structure. This function returns JNI_FALSE if * an error occurs. diff --git a/jdk/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c b/jdk/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c index 016b04f8d1055965c137b823edc3f0814c41c447..6d117bef5e9c0c83390851f6f58f26f9509fd291 100644 --- a/jdk/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c +++ b/jdk/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, 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 @@ -49,6 +49,11 @@ * Native methods */ +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /* * Class: sun_instrument_InstrumentationImpl * Method: isModifiableClass0 diff --git a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c index 06e0a0e5f44763e61d7ffd15477b2cfaf858741e..0c57f8b289deb79631e2cda2f95baab0a4b1ad23 100644 --- a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c +++ b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, 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 @@ -141,7 +141,7 @@ convertCapabilityAtrributes(const jarAttribute* attributes, JPLISAgent* agent) { * to create boot class path segments to append to the boot class path. */ JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) { +DEF_Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) { JPLISInitializationError initerror = JPLIS_INIT_ERROR_NONE; jint result = JNI_OK; JPLISAgent * agent = NULL; @@ -290,7 +290,7 @@ Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) { * the JPLIS library. */ JNIEXPORT jint JNICALL -Agent_OnAttach(JavaVM* vm, char *args, void * reserved) { +DEF_Agent_OnAttach(JavaVM* vm, char *args, void * reserved) { JPLISInitializationError initerror = JPLIS_INIT_ERROR_NONE; jint result = JNI_OK; JPLISAgent * agent = NULL; @@ -435,7 +435,7 @@ Agent_OnAttach(JavaVM* vm, char *args, void * reserved) { JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *vm) { +DEF_Agent_OnUnload(JavaVM *vm) { } diff --git a/jdk/src/java.instrument/share/native/libinstrument/JarFacade.h b/jdk/src/java.instrument/share/native/libinstrument/JarFacade.h index c0351b658ed1765b24683be1ba01837dee2d2c18..d13765e8ce6c92c15c3c79c62c4e50aceca7aa8f 100644 --- a/jdk/src/java.instrument/share/native/libinstrument/JarFacade.h +++ b/jdk/src/java.instrument/share/native/libinstrument/JarFacade.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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,10 @@ * questions. */ +#ifdef STATIC_BUILD +#define getAttribute JarGetAttribute +#endif + typedef struct _jarAttribute { char* name; char* value; diff --git a/jdk/src/java.instrument/share/native/libinstrument/Utilities.h b/jdk/src/java.instrument/share/native/libinstrument/Utilities.h index 6e6abad329d30e2b797befbabbf4544f681a1e7b..4a6767e879dfaac5ae7ae718a188cee4b2574b08 100644 --- a/jdk/src/java.instrument/share/native/libinstrument/Utilities.h +++ b/jdk/src/java.instrument/share/native/libinstrument/Utilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, 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 @@ -32,6 +32,13 @@ #include <jni.h> #include <jvmti.h> +#include "jni_util.h" + +#ifdef STATIC_BUILD +#define allocate instAllocate +#define deallocate instDeallocate +#endif + #ifdef __cplusplus extern "C" { diff --git a/jdk/src/java.management/share/classes/sun/management/BaseOperatingSystemImpl.java b/jdk/src/java.management/share/classes/sun/management/BaseOperatingSystemImpl.java index a40e0b04f932b678c1ae6f38b121b6fe19364c1b..dc165747c98f6738be1e128fc89fb149f853111e 100644 --- a/jdk/src/java.management/share/classes/sun/management/BaseOperatingSystemImpl.java +++ b/jdk/src/java.management/share/classes/sun/management/BaseOperatingSystemImpl.java @@ -28,7 +28,7 @@ package sun.management; import java.lang.management.OperatingSystemMXBean; import java.lang.management.ManagementFactory; import javax.management.ObjectName; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; /** * Implementation class for the operating system. diff --git a/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java b/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java index 740f483a44f5e85fe68619863893cedf60b456a9..3cc0acb8ffe05cde143c7b096270ea36efa00c8e 100644 --- a/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java +++ b/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java @@ -51,7 +51,7 @@ public class ManagementFactoryHelper { static { // make sure that the management lib is loaded within // java.lang.management.ManagementFactory - sun.misc.Unsafe.getUnsafe().ensureClassInitialized(ManagementFactory.class); + jdk.internal.misc.Unsafe.getUnsafe().ensureClassInitialized(ManagementFactory.class); } private static final VMManagement jvm = new VMManagementImpl(); diff --git a/jdk/src/java.management/share/native/libmanagement/management.c b/jdk/src/java.management/share/native/libmanagement/management.c index 65e073b61a2c26a4f4f44a1bc8815c62f30cbedf..d909416719e4364a5a3360e3ef00019ed2cfc7a4 100644 --- a/jdk/src/java.management/share/native/libmanagement/management.c +++ b/jdk/src/java.management/share/native/libmanagement/management.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, 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 @@ -25,6 +25,7 @@ #include <stdio.h> #include <jni.h> +#include "jni_util.h" #include "jvm.h" #include "management.h" @@ -35,7 +36,7 @@ JavaVM* jvm = NULL; jint jmm_version = 0; JNIEXPORT jint JNICALL - JNI_OnLoad(JavaVM *vm, void *reserved) { + DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv* env; jvm = vm; diff --git a/jdk/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m b/jdk/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m index f25f8684d6fb016ce9987a07483f8df7b49123c7..269981aecd5103e7b08d3b0b8a59302b12d56cc3 100644 --- a/jdk/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m +++ b/jdk/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m @@ -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 @@ -64,6 +64,11 @@ #include "jlong.h" #include "jvm.h" +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + // Throw an OutOfMemoryError with the given message. static void throwOutOfMemoryError(JNIEnv *env, const char *msg) diff --git a/jdk/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c b/jdk/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c index 757f64c34f0de64e4c44f33f474d319e544e7d98..05dc673ae6d6390ae8a9bc9bc86ee713037e67e9 100644 --- a/jdk/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c +++ b/jdk/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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,6 +35,11 @@ #include <utime.h> #include "jni_util.h" +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + JNIEXPORT jint JNICALL Java_java_util_prefs_FileSystemPreferences_chmod(JNIEnv *env, jclass thisclass, jstring java_fname, jint permission) { diff --git a/jdk/src/java.prefs/windows/native/libprefs/WindowsPreferences.c b/jdk/src/java.prefs/windows/native/libprefs/WindowsPreferences.c index ef3ff3564235d811a5d4745b21a6d8e05b94b50d..265f894fe510d3caa61db89e03f0bbf17baf90b3 100644 --- a/jdk/src/java.prefs/windows/native/libprefs/WindowsPreferences.c +++ b/jdk/src/java.prefs/windows/native/libprefs/WindowsPreferences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, 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 @@ -31,6 +31,12 @@ #ifdef __cplusplus extern "C" { #endif + +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegOpenKey (JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey, jint securityMask) { HKEY handle; diff --git a/jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c b/jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c index 518462e6ae243d62a652822b181f75d7dc6ab60c..dc95524eb09f2a8bb7aed2653413fe8b18330370 100644 --- a/jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c +++ b/jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c @@ -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 @@ -28,6 +28,8 @@ #import <string.h> #import <time.h> +#include "jni_util.h" + /* * Based largely on klist.c, * @@ -92,7 +94,7 @@ static jclass FindClass(JNIEnv *env, char *className) * Class: sun_security_krb5_KrbCreds * Method: JNI_OnLoad */ -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) +JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *jvm, void *reserved) { JNIEnv *env; @@ -191,7 +193,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) * Class: sun_security_jgss_KrbCreds * Method: JNI_OnUnload */ -JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserved) +JNIEXPORT void JNICALL DEF_JNI_OnUnload(JavaVM *jvm, void *reserved) { JNIEnv *env; diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KerberosSecrets.java b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KerberosSecrets.java index 44f2f0f94aa8a986f105dc08d5883873977df876..5d68c4ec3a8685beab63575318fd724bb339c5a7 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KerberosSecrets.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KerberosSecrets.java @@ -26,7 +26,7 @@ package sun.security.krb5; import javax.security.auth.kerberos.KeyTab; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; public class KerberosSecrets { private static final Unsafe unsafe = Unsafe.getUnsafe(); diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java index 4b60b1a99c25cc833170b655dea3c85db6cd3331..e60507fe443280508d9549f4badece9801883293 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java @@ -187,10 +187,10 @@ public class PrincipalName implements Cloneable { } private static final long NAME_STRINGS_OFFSET; - private static final sun.misc.Unsafe UNSAFE; + private static final jdk.internal.misc.Unsafe UNSAFE; static { try { - sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); NAME_STRINGS_OFFSET = unsafe.objectFieldOffset( PrincipalName.class.getDeclaredField("nameStrings")); UNSAFE = unsafe; diff --git a/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.c b/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.c index 7095af4e17edfbd7a0f7845d6c3090f4596654b7..033f09947961ba1543957d3a19e3c3e541529ec1 100644 --- a/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.c +++ b/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.c @@ -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 @@ -27,6 +27,7 @@ #include "NativeFunc.h" #include "jlong.h" #include <jni.h> +#include "jni_util.h" const int JAVA_DUPLICATE_TOKEN_CODE = 19; /* DUPLICATE_TOKEN */ const int JAVA_OLD_TOKEN_CODE = 20; /* OLD_TOKEN */ @@ -94,7 +95,7 @@ jfieldID FID_NativeGSSContext_actualMech; int JGSS_DEBUG; JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *jvm, void *reserved) { +DEF_JNI_OnLoad(JavaVM *jvm, void *reserved) { JNIEnv *env; jclass cls; @@ -363,7 +364,7 @@ JNI_OnLoad(JavaVM *jvm, void *reserved) { } JNIEXPORT void JNICALL -JNI_OnUnload(JavaVM *jvm, void *reserved) { +DEF_JNI_OnUnload(JavaVM *jvm, void *reserved) { JNIEnv *env; if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) { diff --git a/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.h b/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.h index 78f72269f8c62200d6ec846445b155aa63b71060..3fe1903726d7dcf5ccd01f0da3e95a7e642dcc2e 100644 --- a/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.h +++ b/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.h @@ -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 @@ -54,9 +54,6 @@ extern "C" { extern jstring getMinorMessage(JNIEnv *, jobject, OM_uint32); extern int sameMech(gss_OID, gss_OID); - JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *, void *); - JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *, void *); - extern int JGSS_DEBUG; extern jclass CLS_Object; diff --git a/jdk/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c b/jdk/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c index 554eb63c19decf4bb6f762a0fd914037363900e6..d5424cf4f5f8692c9d11a1d41681816fb719e59a 100644 --- a/jdk/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c +++ b/jdk/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c @@ -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 @@ -42,6 +42,7 @@ #include <lmcons.h> #include <lmapibuf.h> #include <jni.h> +#include "jni_util.h" #include <winsock.h> #undef LSA_SUCCESS @@ -107,7 +108,7 @@ jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime); * Method: JNI_OnLoad */ -JNIEXPORT jint JNICALL JNI_OnLoad( +JNIEXPORT jint JNICALL DEF_JNI_OnLoad( JavaVM *jvm, void *reserved) { @@ -329,7 +330,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad( * Method: JNI_OnUnload */ -JNIEXPORT void JNICALL JNI_OnUnload( +JNIEXPORT void JNICALL DEF_JNI_OnUnload( JavaVM *jvm, void *reserved) { diff --git a/jdk/src/java.smartcardio/share/native/libj2pcsc/pcsc.c b/jdk/src/java.smartcardio/share/native/libj2pcsc/pcsc.c index b837234761d88dfe5fd23e93d2d4d6cbc51def1e..a10240acf1d4583364a5bfb8700ae62dd6d2a6dc 100644 --- a/jdk/src/java.smartcardio/share/native/libj2pcsc/pcsc.c +++ b/jdk/src/java.smartcardio/share/native/libj2pcsc/pcsc.c @@ -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 @@ -55,6 +55,8 @@ #include "pcsc_md.h" +#include "jni_util.h" + #define MAX_STACK_BUFFER_SIZE 8192 // make the buffers larger than what should be necessary, just in case @@ -101,7 +103,7 @@ jboolean handleRV(JNIEnv* env, LONG code) { } } -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { +JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_4; } diff --git a/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c b/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c index f7c790d078d009687ba46cfd6f2ce67473081aa3..08ca4c481ea27ac3a7955758352d8b9baaafbdab 100644 --- a/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c +++ b/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c @@ -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 @@ -49,6 +49,11 @@ } while((_result == -1) && (errno == EINTR)); \ } while(0) +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /* * Defines a callback that is invoked for each process */ diff --git a/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c b/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c index 41778b584c8e61415c38bc7e63e03cb572ab5448..0f75dfe4e3d0db592aca164d6323b2a28041bcf1 100644 --- a/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c +++ b/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c @@ -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 @@ -50,6 +50,11 @@ } while((_result == -1) && (errno == EINTR)); \ } while(0) +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /* * Class: sun_tools_attach_VirtualMachineImpl * Method: socket diff --git a/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c b/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c index 8880af6eefa225e7ee6c1bc738f15ae1fbeb7f18..fb40983f3be884926bd126c4837cbfaabf2ac9ef 100644 --- a/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c +++ b/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c @@ -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 @@ -45,6 +45,11 @@ } while((_result == -1) && (errno == EINTR)); \ } while(0) +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /* * Class: sun_tools_attach_VirtualMachineImpl * Method: open diff --git a/jdk/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c b/jdk/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c index 3a85591db4a6ead89a06af85043edb13962f71d5..d7bdcc12fcbae248c89e7fed21f2a964fc201ab1 100644 --- a/jdk/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c +++ b/jdk/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c @@ -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 @@ -87,6 +87,10 @@ typedef struct { #define ERR_OPEN_JVM_FAIL 200 #define ERR_GET_ENQUEUE_FUNC_FAIL 201 +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad /* * Code copied to target process diff --git a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template index e1810bd9268e5033259786120aaad0d297beacf5..2099fbb1ad3b190e1c525fae5634ebfcebb2e36b 100644 --- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template +++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template @@ -51,12 +51,12 @@ public class Big5_Solaris extends Charset implements HistoricallyNamedCharset public CharsetDecoder newDecoder() { initb2c(); - return new DoubleByte.Decoder(this, b2c, b2cSB, 0x40, 0xfe); + return new DoubleByte.Decoder(this, b2c, b2cSB, 0x40, 0xfe, true); } public CharsetEncoder newEncoder() { initc2b(); - return new DoubleByte.Encoder(this, c2b, c2bIndex); + return new DoubleByte.Encoder(this, c2b, c2bIndex, true); } static char[][] b2c; diff --git a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java index 513dc55f432b1fc5d6c48169098b13e7cca7a01b..aeb4dedfdd682f0dc82f03add88ca7bf35854ad9 100644 --- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java +++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java @@ -62,7 +62,7 @@ public class IBM834 extends Charset protected static class Encoder extends DoubleByte.Encoder_DBCSONLY { public Encoder(Charset cs) { super(cs, new byte[] {(byte)0xfe, (byte)0xfe}, - IBM933.c2b, IBM933.c2bIndex); + IBM933.c2b, IBM933.c2bIndex, false); } public int encodeChar(char ch) { diff --git a/jdk/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp b/jdk/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp index 5c07645d0dca8477ed629e9f5c78db81e146b92d..31c2d0748974e53a340a4e4ad406e635d31e729f 100644 --- a/jdk/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp +++ b/jdk/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, 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 @@ -24,6 +24,7 @@ */ #include <jni.h> +#include "jni_util.h" #include "impl/ecc_impl.h" #define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException" @@ -35,6 +36,11 @@ extern "C" { +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /* * Throws an arbitrary Java exception. */ diff --git a/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp b/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp index 161c2aed08895681bcde1db98fe557930956f4a1..41f3367bc4ee75e194a949515b5f9f5e1c5515fd 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp +++ b/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.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 @@ -29,6 +29,7 @@ // #include <jni.h> +#include "jni_util.h" #include <stdlib.h> #include <string.h> #include <windows.h> @@ -50,6 +51,11 @@ extern "C" { +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + /* * Throws an arbitrary Java exception. * The exception message is a Windows system error message. diff --git a/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_general.c b/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_general.c index 604ae31158d1cc5c02811ad6be9a8368a7a7efe1..852a1478a72acc8f48ceed9cd546cc0c3d6cf84f 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_general.c +++ b/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_general.c @@ -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. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -73,7 +73,7 @@ jclass jLongClass; JavaVM* jvm = NULL; -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { +JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { jvm = vm; return JNI_VERSION_1_4; } diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c index 8bd81e6b7d15a4842acc5b7493c5c12fd9e4a688..84abb867db1ba3b026e6638970416c39bbedaa5f 100644 --- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c +++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c @@ -27,6 +27,7 @@ #include <string.h> #include <strings.h> #include <jni.h> +#include "jni_util.h" #include <libsoftcrypto.h> #include "nativeCrypto.h" #include "nativeFunc.h" @@ -59,7 +60,7 @@ void throwOutOfMemoryError(JNIEnv *env, const char *msg) (*env)->DeleteLocalRef(env, jExClass); } -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { +JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_4; } diff --git a/jdk/src/jdk.deploy.osx/macosx/native/libapplescriptengine/AppleScriptEngine.m b/jdk/src/jdk.deploy.osx/macosx/native/libapplescriptengine/AppleScriptEngine.m index b49219b8feba0636b0757fb2004de544a4ff8432..33c8cdc379b80c1e1b84f3965f36b44ab103f241 100644 --- a/jdk/src/jdk.deploy.osx/macosx/native/libapplescriptengine/AppleScriptEngine.m +++ b/jdk/src/jdk.deploy.osx/macosx/native/libapplescriptengine/AppleScriptEngine.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, 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 @@ -26,6 +26,10 @@ #import "apple_applescript_AppleScriptEngine.h" #import "apple_applescript_AppleScriptEngineFactory.h" +// Must include this before JavaNativeFoundation.h to get jni.h from build +#include "jni.h" +#include "jni_util.h" + #import <JavaNativeFoundation/JavaNativeFoundation.h> #import "NS_Java_ConversionUtils.h" @@ -33,6 +37,10 @@ //#define DEBUG 1 +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad /* * Class: apple_applescript_AppleScriptEngineFactory diff --git a/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m b/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m index 2586d5e02d579b52e455a5fd978c3eb40aa5a083..cdeac0d435da89afafbeac6611ff7d46eaf18de8 100644 --- a/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m +++ b/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, 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,11 +23,21 @@ * questions. */ +/* + * Must include this before JavaNativeFoundation.h to get jni.h from build + */ +#include "jni.h" +#include "jni_util.h" + #import "com_apple_concurrent_LibDispatchNative.h" #import <dispatch/dispatch.h> #import <JavaNativeFoundation/JavaNativeFoundation.h> +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad /* * Class: com_apple_concurrent_LibDispatchNative diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c index 8ae64d19f49b57e01c8dee2137e2fd529fb7ae5b..c8944a499395df8d5af4727998c389e3d527cd04 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c @@ -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 @@ -194,7 +194,7 @@ compatible_versions(jint major_runtime, jint minor_runtime, * Returning JNI_ERR will cause the java_g VM to core dump, be careful. */ JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *vm, char *options, void *reserved) +DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jvmtiError error; jvmtiCapabilities needed_capabilities; @@ -380,7 +380,7 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) } JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *vm) +DEF_Agent_OnUnload(JavaVM *vm) { gdata->isLoaded = JNI_FALSE; diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.h index b8c5b25c5dd18c164f7a07d1227475a91ffbfb61..794e349d895a5f0ca395825ad3e0228c0643f15a 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.h +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2005, 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 @@ -39,7 +39,4 @@ void debugInit_reset(JNIEnv *env); void debugInit_exit(jvmtiError, const char *); void forceExit(int); -JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *, char *, void *); -JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *); - #endif diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/transport.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/transport.c index b8e47acdf416bece1e8fbae4a3bdf3b1f8c8a98f..e9b83f200f425b2b20c638e2a671c0f214a62a64 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/transport.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/transport.c @@ -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 @@ -101,9 +101,10 @@ findTransportOnLoad(void *handle) static void * loadTransportLibrary(const char *libdir, const char *name) { + char buf[MAXPATHLEN*2+100]; +#ifndef STATIC_BUILD void *handle; char libname[MAXPATHLEN+2]; - char buf[MAXPATHLEN*2+100]; const char *plibdir; /* Convert libdir from UTF-8 to platform encoding */ @@ -125,6 +126,9 @@ loadTransportLibrary(const char *libdir, const char *name) /* dlopen (unix) / LoadLibrary (windows) the transport library */ handle = dbgsysLoadLibrary(libname, buf, sizeof(buf)); return handle; +#else + return (dbgsysLoadLibrary(NULL, buf, sizeof(buf))); +#endif } /* diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h index 4a08823a2aaafa95f0d9a641ca55951ebc6c1115..9ccb38ce09bec5c28ba1cbbc47c9e23f4b31ef90 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h @@ -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 @@ -277,18 +277,6 @@ typedef struct ObjectBatch { */ #define MOD_SYNTHETIC 0xf0000000 /* not in source code */ -/* - * jlong conversion macros - */ -#define jlong_zero ((jlong) 0) -#define jlong_one ((jlong) 1) - -#define jlong_to_ptr(a) ((void*)(intptr_t)(a)) -#define ptr_to_jlong(a) ((jlong)(intptr_t)(a)) -#define jint_to_jlong(a) ((jlong)(a)) -#define jlong_to_jint(a) ((jint)(a)) - - /* * util funcs */ diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/vm_interface.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/vm_interface.h index 341e2aa25618bbb9a481d2a92efcc924b5500ebe..769a7f5678f21a0ef2193cd05aada47234b30155 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/vm_interface.h +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/vm_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 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 @@ -33,6 +33,7 @@ #include <jni.h> #include <jvm.h> #include <jvmti.h> +#include "jni_util.h" #include "log_messages.h" diff --git a/jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.c b/jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.c index 9d22c0a10a6e0528a231fb45577b7a4c1ba52999..dbb9f0271374c2ac5155f93b1b9796cd3ec024fe 100644 --- a/jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.c +++ b/jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.c @@ -25,6 +25,7 @@ #include <stdio.h> #include <jni.h> +#include "jni_util.h" #include "jvm.h" #include "management_ext.h" @@ -35,7 +36,7 @@ JavaVM* jvm = NULL; jint jmm_version = 0; JNIEXPORT jint JNICALL - JNI_OnLoad(JavaVM *vm, void *reserved) { + DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv* env; jvm = vm; diff --git a/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp b/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp index 40a10055ea588b0fa18efbf8401b9d2650ebed62..a14126c195235e9b4f1ab1f99baefa6172cb52de 100644 --- a/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp +++ b/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -77,6 +77,8 @@ void mkdirs(int oklen, char* path) { #ifndef PRODUCT +#ifndef STATIC_BUILD +// use the definition in libjvm when building statically void breakpoint() { } // hook for debugger int assert_failed(const char* p) { char message[1<<12]; @@ -87,6 +89,7 @@ int assert_failed(const char* p) { return 0; } #endif +#endif void unpack_abort(const char* msg, unpacker* u) { if (msg == null) msg = "corrupt pack file or internal error"; diff --git a/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp b/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp index 4915590aeaa20e7af7d5b3d874242a42cb339bd0..069df3f3a354cf3c9f3ee952eccded44e476b73f 100644 --- a/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp +++ b/jdk/src/jdk.pack200/share/native/libunpack/jni.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 @@ -95,6 +95,11 @@ static char* dbg = null; } while (JNI_FALSE) #endif +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + static jlong read_input_via_jni(unpacker* self, void* buf, jlong minlen, jlong maxlen); diff --git a/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c b/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c index 9c3efc0cd93c938dbd687e71dae0b1133f9749a5..9496497fd112ed333326a69e964a2ea64fc71aad 100644 --- a/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c +++ b/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c @@ -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 @@ -43,7 +43,7 @@ static jmethodID isaCtrID = 0; static const char* nativeSctpLib = "libsctp.so.1"; static jboolean funcsLoaded = JNI_FALSE; -JNIEXPORT jint JNICALL JNI_OnLoad +JNIEXPORT jint JNICALL DEF_JNI_OnLoad (JavaVM *vm, void *reserved) { return JNI_VERSION_1_2; } diff --git a/jdk/src/jdk.security.auth/unix/native/libjaas/Unix.c b/jdk/src/jdk.security.auth/unix/native/libjaas/Unix.c index e4db557ce47f19f5b0d16ad31cd2f347170a086e..76737ab76a3345779c2781f9d634fa4c808b2a3e 100644 --- a/jdk/src/jdk.security.auth/unix/native/libjaas/Unix.c +++ b/jdk/src/jdk.security.auth/unix/native/libjaas/Unix.c @@ -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 @@ -28,6 +28,7 @@ #endif #include <jni.h> +#include "jni_util.h" #include "com_sun_security_auth_module_UnixSystem.h" #include <stdio.h> #include <pwd.h> @@ -36,6 +37,11 @@ #include <stdlib.h> #include <string.h> +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + JNIEXPORT void JNICALL Java_com_sun_security_auth_module_UnixSystem_getUnixInfo (JNIEnv *env, jobject obj) { diff --git a/jdk/src/jdk.security.auth/windows/native/libjaas/nt.c b/jdk/src/jdk.security.auth/windows/native/libjaas/nt.c index 03a5c7afeb02ccbfa25832f354661b90f1c47cc8..e41386c87ac1ca78fadaf5558c213a7b915ec6f6 100644 --- a/jdk/src/jdk.security.auth/windows/native/libjaas/nt.c +++ b/jdk/src/jdk.security.auth/windows/native/libjaas/nt.c @@ -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 @@ -24,6 +24,7 @@ */ #include <jni.h> +#include "jni_util.h" #include "com_sun_security_auth_module_NTSystem.h" #include <windows.h> @@ -49,6 +50,11 @@ static void throwIllegalArgumentException(JNIEnv *env, const char *msg) { (*env)->ThrowNew(env, clazz, msg); } +/* + * Declare library specific JNI_Onload entry if static build + */ +DEF_STATIC_JNI_OnLoad + JNIEXPORT jlong JNICALL Java_com_sun_security_auth_module_NTSystem_getImpersonationToken0 (JNIEnv *env, jobject obj) { diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 652647362d9d1c31ab41dc65bfa4bcdca53d3774..87d655007f2f2b4fe29b8e14eb564310fb82960c 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -363,6 +363,18 @@ com/sun/jdi/GetLocalVariables4Test.sh windows-all # 8062512 java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.java generic-all +# 8076458 +java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java generic-all + +# 8130337 +java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java generic-all + +# 8080165, 8085982 +java/util/Arrays/ParallelPrefix.java generic-all + +# 8079538 +java/util/BitSet/BitSetStreamTest.java generic-all + ############################################################################ # jdk_instrument diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index 72fc5e9dd061392a43d86ab4850cd4a912be8537..1ec1b7d375cc02bcca7f6318c9333e321d103e11 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -28,7 +28,9 @@ tier1 = \ :jdk_lang \ -java/lang/ProcessHandle/TreeTest.java \ + -java/util/zip/TestLocalTime.java \ :jdk_util \ + -java/util/concurrent/Phaser/Basic.java \ sun/nio/cs/ISO8859x.java \ java/nio/Buffer \ com/sun/crypto/provider/Cipher \ @@ -36,6 +38,8 @@ tier1 = \ tier2 = \ java/lang/ProcessHandle/TreeTest.java \ + java/util/zip/TestLocalTime.java \ + java/util/concurrent/Phaser/Basic.java \ :jdk_io \ :jdk_nio \ -sun/nio/cs/ISO8859x.java \ diff --git a/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java b/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java index d1797145fa98812cf268cb5a8d0e68a7589783b8..fe48073a6b39aef70e67c4eb203f508bb1e648fc 100644 --- a/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java +++ b/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java @@ -47,6 +47,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLHandshakeException; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; @@ -234,6 +235,12 @@ class DeadServerTimeoutSSLTest extends DeadServerTest { if (e.getCause() instanceof SocketTimeoutException) { // SSL connect will timeout via readReply using // SocketTimeoutException + e.printStackTrace(); + pass(); + } else if (e.getCause() instanceof SSLHandshakeException + && e.getCause().getCause() instanceof EOFException) { + // test seems to be failing intermittently on some + // platforms. pass(); } else { fail(e); diff --git a/jdk/test/java/lang/ProcessBuilder/Basic.java b/jdk/test/java/lang/ProcessBuilder/Basic.java index 5a39cdc454fc87d41acda2c66275098035fbb50d..7be2aa6ba71fa5f035d23e0b4c50511b4eb07666 100644 --- a/jdk/test/java/lang/ProcessBuilder/Basic.java +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java @@ -1248,7 +1248,7 @@ public class Basic { () -> p.toHandle(), () -> p.supportsNormalTermination(), () -> p.children(), - () -> p.allChildren()); + () -> p.descendants()); } diff --git a/jdk/test/java/lang/ProcessHandle/OnExitTest.java b/jdk/test/java/lang/ProcessHandle/OnExitTest.java index ea9dfc65e0da8191ba1934341860604d28daf1f6..9c7a5193db6a47466664752a860c49e4aebf60be 100644 --- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java +++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java @@ -129,7 +129,7 @@ public class OnExitTest extends ProcessUtil { printf(" You can try to increase the timeout or%n"); printf(" you can try to use a faster VM (i.e. not a debug version).%n"); } - children = getAllChildren(procHandle); + children = getDescendants(procHandle); ConcurrentHashMap<ProcessHandle, CompletableFuture<ProcessHandle>> completions = new ConcurrentHashMap<>(); diff --git a/jdk/test/java/lang/ProcessHandle/PermissionTest.java b/jdk/test/java/lang/ProcessHandle/PermissionTest.java index 863f421afd7592410cd63494a2c7d2ce90798457..042b9d1e8186005b24b2c67fb5801d537735e128 100644 --- a/jdk/test/java/lang/ProcessHandle/PermissionTest.java +++ b/jdk/test/java/lang/ProcessHandle/PermissionTest.java @@ -62,9 +62,9 @@ public class PermissionTest { } @Test - public void allChildrenWithPermission() { + public void descendantsWithPermission() { Policy.setPolicy(new TestPolicy(new RuntimePermission("manageProcess"))); - currentHndl.allChildren(); + currentHndl.descendants(); } @Test @@ -122,7 +122,7 @@ public class PermissionTest { @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class) public void noPermissionAllChildren() { - currentHndl.allChildren(); + currentHndl.descendants(); } @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class) diff --git a/jdk/test/java/lang/ProcessHandle/ProcessUtil.java b/jdk/test/java/lang/ProcessHandle/ProcessUtil.java index 328012f1a3014420f671b7aa7b285d95cf0936e8..c0c6916f9710bed2907c84f571ff5e38ebb70dc1 100644 --- a/jdk/test/java/lang/ProcessHandle/ProcessUtil.java +++ b/jdk/test/java/lang/ProcessHandle/ProcessUtil.java @@ -63,8 +63,8 @@ public abstract class ProcessUtil { * @param ph the Process to get children of * @return a list of child ProcessHandles */ - public static List<ProcessHandle> getAllChildren(ProcessHandle ph) { - return ph.allChildren() + public static List<ProcessHandle> getDescendants(ProcessHandle ph) { + return ph.descendants() .filter(ProcessUtil::isNotWindowsConsole) .collect(Collectors.toList()); } @@ -117,7 +117,7 @@ public abstract class ProcessUtil { // ignore } } - subprocesses = getAllChildren(ph); + subprocesses = getDescendants(ph); count = subprocesses.size(); System.out.printf(" waiting for subprocesses of %s to start," + " expected: %d, current: %d%n", ph, nchildren, count); @@ -133,7 +133,7 @@ public abstract class ProcessUtil { * @return the ProcessHandle */ public static ProcessHandle destroyProcessTree(ProcessHandle p) { - Stream<ProcessHandle> children = p.allChildren().filter(ProcessUtil::isNotWindowsConsole); + Stream<ProcessHandle> children = p.descendants().filter(ProcessUtil::isNotWindowsConsole); children.forEach(ph -> { System.out.printf("destroyProcessTree destroyForcibly%n"); printProcess(ph); diff --git a/jdk/test/java/lang/ProcessHandle/TreeTest.java b/jdk/test/java/lang/ProcessHandle/TreeTest.java index ea12d3f361f376baae5e3b124f79c5d98f185a6c..39b00b088b0571f51c8c1c636ad70cef6d0469cb 100644 --- a/jdk/test/java/lang/ProcessHandle/TreeTest.java +++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java @@ -193,21 +193,21 @@ public class TreeTest extends ProcessUtil { } // show the complete list of children (for debug) - List<ProcessHandle> allChildren = getAllChildren(p1Handle); - printf(" allChildren: %s%n", - allChildren.stream().map(p -> p.getPid()) - .collect(Collectors.toList())); + List<ProcessHandle> descendants = getDescendants(p1Handle); + printf(" descendants: %s%n", + descendants.stream().map(p -> p.getPid()) + .collect(Collectors.toList())); - // Verify that all spawned children show up in the allChildren List + // Verify that all spawned children show up in the descendants List processes.forEach((p, parent) -> { Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p); - Assert.assertTrue(allChildren.contains(p), "Spawned child should be listed in allChildren: " + p); + Assert.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p); }); // Closing JavaChild's InputStream will cause all children to exit p1.getOutputStream().close(); - for (ProcessHandle p : allChildren) { + for (ProcessHandle p : descendants) { try { p.onExit().get(); // wait for the child to exit } catch (ExecutionException e) { @@ -228,9 +228,9 @@ public class TreeTest extends ProcessUtil { /** * Test destroy of processes. * A JavaChild is started and it starts three children. - * Each one is then checked to be alive and listed by allChildren + * Each one is then checked to be alive and listed by descendants * and forcibly destroyed. - * After they exit they should no longer be listed by allChildren. + * After they exit they should no longer be listed by descendants. */ @Test public static void test3() { @@ -263,24 +263,24 @@ public class TreeTest extends ProcessUtil { Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), "Timeout waiting for processes to start"); - // Debugging; list allChildren that are not expected in processes - List<ProcessHandle> allChildren = ProcessUtil.getAllChildren(p1Handle); - long count = allChildren.stream() + // Debugging; list descendants that are not expected in processes + List<ProcessHandle> descendants = ProcessUtil.getDescendants(p1Handle); + long count = descendants.stream() .filter(ph -> !processes.containsKey(ph)) .count(); if (count > 0) { - allChildren.stream() + descendants.stream() .filter(ph -> !processes.containsKey(ph)) .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: ")); ProcessUtil.logTaskList(); - Assert.assertEquals(0, count, "Extra processes in allChildren"); + Assert.assertEquals(0, count, "Extra processes in descendants"); } - // Verify that all spawned children are alive, show up in the allChildren list + // Verify that all spawned children are alive, show up in the descendants list // then destroy them processes.forEach((p, parent) -> { Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p); - Assert.assertTrue(allChildren.contains(p), "Spawned child should be listed in allChildren: " + p); + Assert.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p); p.destroyForcibly(); }); Assert.assertEquals(processes.size(), newChildren, "Wrong number of children"); @@ -305,8 +305,8 @@ public class TreeTest extends ProcessUtil { p1.destroyForcibly(); p1.waitFor(); - // Verify that none of the spawned children are still listed by allChildren - List<ProcessHandle> remaining = getAllChildren(self); + // Verify that none of the spawned children are still listed by descendants + List<ProcessHandle> remaining = getDescendants(self); Assert.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited"); remaining = remaining.stream().filter(processes::containsKey).collect(Collectors.toList()); Assert.assertEquals(remaining.size(), 0, "Subprocess(es) should have exited: " + remaining); @@ -415,28 +415,28 @@ public class TreeTest extends ProcessUtil { Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), "Timeout waiting for processes to start"); - // Debugging; list allChildren that are not expected in processes - List<ProcessHandle> allChildren = ProcessUtil.getAllChildren(p1Handle); - long count = allChildren.stream() + // Debugging; list descendants that are not expected in processes + List<ProcessHandle> descendants = ProcessUtil.getDescendants(p1Handle); + long count = descendants.stream() .filter(ph -> !processes.containsKey(ph)) .count(); if (count > 0) { - allChildren.stream() + descendants.stream() .filter(ph -> !processes.containsKey(ph)) .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: ")); ProcessUtil.logTaskList(); - Assert.assertEquals(0, count, "Extra processes in allChildren"); + Assert.assertEquals(0, count, "Extra processes in descendants"); } Assert.assertEquals(getChildren(p1Handle).size(), factor, "expected direct children"); - count = getAllChildren(p1Handle).size(); + count = getDescendants(p1Handle).size(); long totalChildren = factor * factor * factor + factor * factor + factor; Assert.assertTrue(count >= totalChildren, "expected at least " + totalChildren + ", actual: " + count); - List<ProcessHandle> subprocesses = getAllChildren(p1Handle); - printf(" allChildren: %s%n", + List<ProcessHandle> subprocesses = getDescendants(p1Handle); + printf(" descendants: %s%n", subprocesses.stream().map(p -> p.getPid()) .collect(Collectors.toList())); diff --git a/jdk/test/java/lang/String/Chars.java b/jdk/test/java/lang/String/Chars.java new file mode 100644 index 0000000000000000000000000000000000000000..ab6771b8e0b0412adabe08b11b6f50e9c7111f96 --- /dev/null +++ b/jdk/test/java/lang/String/Chars.java @@ -0,0 +1,89 @@ +/* + * 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 8054307 + @summary test chars() and codePoints() +*/ + +import java.util.Arrays; +import java.util.Random; + +public class Chars { + + public static void main(String[] args) { + Random r = new Random(); + for (int i = 0; i < 10; i++) { + int n = 100 + r.nextInt(100); + char[] cc = new char[n]; + int[] ccExp = new int[n]; + int[] cpExp = new int[n]; + // latin1 + for (int j = 0; j < n; j++) { + cc[j] = (char)(ccExp[j] = cpExp[j] = r.nextInt(0x80)); + } + testChars(cc, ccExp); + testCPs(cc, cpExp); + + // bmp without surrogates + for (int j = 0; j < n; j++) { + cc[j] = (char)(ccExp[j] = cpExp[j] = r.nextInt(0x8000)); + } + testChars(cc, ccExp); + testCPs(cc, cpExp); + + // bmp with surrogates + int k = 0; + for (int j = 0; j < n; j++) { + if (j % 9 == 5 && j + 1 < n) { + int cp = 0x10000 + r.nextInt(2000); + cpExp[k++] = cp; + Character.toChars(cp, cc, j); + ccExp[j] = cc[j]; + ccExp[j + 1] = cc[j + 1]; + j++; + } else { + cc[j] = (char)(ccExp[j] = cpExp[k++] = r.nextInt(0x8000)); + } + } + cpExp = Arrays.copyOf(cpExp, k); + testChars(cc, ccExp); + testCPs(cc, cpExp); + } + } + + static void testChars(char[] cc, int[] expected) { + String str = new String(cc); + if (!Arrays.equals(expected, str.chars().toArray())) { + throw new RuntimeException("chars/codePoints() failed!"); + } + } + + static void testCPs(char[] cc, int[] expected) { + String str = new String(cc); + if (!Arrays.equals(expected, str.codePoints().toArray())) { + throw new RuntimeException("chars/codePoints() failed!"); + } + } +} diff --git a/jdk/test/java/lang/String/CompactString/CharAt.java b/jdk/test/java/lang/String/CompactString/CharAt.java new file mode 100644 index 0000000000000000000000000000000000000000..f70c1437e8401cc5a2a92662c1c34e36be3aa4bd --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/CharAt.java @@ -0,0 +1,72 @@ +/* + * 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.util.stream.IntStream; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.charAt. + * @run testng/othervm -XX:+CompactStrings CharAt + * @run testng/othervm -XX:-CompactStrings CharAt + */ + +public class CharAt extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + new Object[] { STRING_L1, new char[] { 'A' } }, + new Object[] { STRING_L2, new char[] { 'A', 'B' } }, + new Object[] { STRING_L4, new char[] { 'A', 'B', 'C', 'D' } }, + new Object[] { STRING_LLONG, + new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } }, + new Object[] { STRING_U1, new char[] { '\uFF21' } }, + new Object[] { STRING_U2, new char[] { '\uFF21', '\uFF22' } }, + new Object[] { STRING_M12, new char[] { '\uFF21', 'A' } }, + new Object[] { STRING_M11, new char[] { 'A', '\uFF21' } }, }; + } + + @Test(dataProvider = "provider") + public void testCharAt(String str, char[] expected) { + map.get(str) + .forEach( + (source, data) -> { + IntStream + .range(0, str.length()) + .forEach( + i -> assertEquals( + str.charAt(i), + expected[i], + String.format( + "testing String(%s).charAt(%d), source : %s, ", + escapeNonASCIIs(data), + i, source))); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/CodePointAt.java b/jdk/test/java/lang/String/CompactString/CodePointAt.java new file mode 100644 index 0000000000000000000000000000000000000000..5333f0bb6b8b8cd95c31ddaf16f1402573f80e53 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/CodePointAt.java @@ -0,0 +1,79 @@ +/* + * 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.util.stream.IntStream; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.codePointAt. + * @run testng/othervm -XX:+CompactStrings CodePointAt + * @run testng/othervm -XX:-CompactStrings CodePointAt + */ + +public class CodePointAt extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_L1, new int[] { 'A' } }, + new Object[] { STRING_L2, new int[] { 'A', 'B' } }, + new Object[] { STRING_L4, new int[] { 'A', 'B', 'C', 'D' } }, + new Object[] { STRING_LLONG, + new int[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } }, + new Object[] { STRING_U1, new int[] { '\uFF21' } }, + new Object[] { STRING_U2, new int[] { '\uFF21', '\uFF22' } }, + new Object[] { STRING_M12, new int[] { '\uFF21', 'A' } }, + new Object[] { STRING_M11, new int[] { 'A', '\uFF21' } }, + new Object[] { + STRING_SUPPLEMENTARY, + new int[] { Character.toCodePoint('\uD801', '\uDC00'), + '\uDC00', + Character.toCodePoint('\uD801', '\uDC01'), + '\uDC01', '\uFF21', 'A' }, } }; + } + + @Test(dataProvider = "provider") + public void testCodePointAt(String str, int[] expected) { + map.get(str) + .forEach( + (source, data) -> { + IntStream + .range(0, str.length()) + .forEach( + i -> assertEquals( + str.codePointAt(i), + expected[i], + String.format( + "testing String(%s).codePointAt(%d), source : %s, ", + escapeNonASCIIs(data), + i, source))); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/CodePointBefore.java b/jdk/test/java/lang/String/CompactString/CodePointBefore.java new file mode 100644 index 0000000000000000000000000000000000000000..81f16bce54c9a064b01acacf7cdf9629cc05af2f --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/CodePointBefore.java @@ -0,0 +1,79 @@ +/* + * 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.util.stream.IntStream; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.codePointBefore. + * @run testng/othervm -XX:+CompactStrings CodePointBefore + * @run testng/othervm -XX:-CompactStrings CodePointBefore + */ + +public class CodePointBefore extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_L1, new int[] { 'A' } }, + new Object[] { STRING_L2, new int[] { 'A', 'B' } }, + new Object[] { STRING_L4, new int[] { 'A', 'B', 'C', 'D' } }, + new Object[] { STRING_LLONG, + new int[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } }, + new Object[] { STRING_U1, new int[] { '\uFF21' } }, + new Object[] { STRING_U2, new int[] { '\uFF21', '\uFF22' } }, + new Object[] { STRING_M12, new int[] { '\uFF21', 'A' } }, + new Object[] { STRING_M11, new int[] { 'A', '\uFF21' } }, + new Object[] { + STRING_SUPPLEMENTARY, + new int[] { '\uD801', Character.toCodePoint('\uD801', '\uDC00'), + '\uD801', Character.toCodePoint('\uD801', '\uDC01'), + '\uFF21', 'A' }, } }; + } + + @Test(dataProvider = "provider") + public void testCodePointBefore(String str, int[] expected) { + map.get(str) + .forEach( + (source, data) -> { + IntStream + .range(0, str.length()) + .forEach( + i -> assertEquals( + str.codePointBefore(i + 1), + expected[i], + String.format( + "testing String(%s).codePointBefore(%d), source : %s, ", + escapeNonASCIIs(data), + i + 1, source))); + }); + } + +} diff --git a/jdk/test/java/lang/String/CompactString/CodePointCount.java b/jdk/test/java/lang/String/CompactString/CodePointCount.java new file mode 100644 index 0000000000000000000000000000000000000000..0ddc82add5d5e7eae2246bd5568589017d40852f --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/CodePointCount.java @@ -0,0 +1,89 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.codePointCount. + * @run testng/othervm -XX:+CompactStrings CodePointCount + * @run testng/othervm -XX:-CompactStrings CodePointCount + */ + +public class CodePointCount extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { new Object[] { STRING_EMPTY, 0, 0, 0 }, + new Object[] { STRING_L1, 0, 1, 1 }, + new Object[] { STRING_L1, 1, 1, 0 }, + new Object[] { STRING_L2, 0, 2, 2 }, + new Object[] { STRING_L2, 0, 1, 1 }, + new Object[] { STRING_L2, 1, 2, 1 }, + new Object[] { STRING_L4, 0, 4, 4 }, + new Object[] { STRING_L4, 0, 1, 1 }, + new Object[] { STRING_L4, 2, 4, 2 }, + new Object[] { STRING_LLONG, 0, 8, 8 }, + new Object[] { STRING_LLONG, 0, 5, 5 }, + new Object[] { STRING_LLONG, 4, 8, 4 }, + new Object[] { STRING_LLONG, 0, 7, 7 }, + new Object[] { STRING_U1, 0, 1, 1 }, + new Object[] { STRING_U2, 0, 2, 2 }, + new Object[] { STRING_U2, 0, 1, 1 }, + new Object[] { STRING_U2, 1, 2, 1 }, + new Object[] { STRING_M12, 0, 2, 2 }, + new Object[] { STRING_M12, 0, 1, 1 }, + new Object[] { STRING_M12, 1, 2, 1 }, + new Object[] { STRING_M11, 0, 2, 2 }, + new Object[] { STRING_M11, 0, 1, 1 }, + new Object[] { STRING_M11, 1, 2, 1 }, + new Object[] { STRING_SUPPLEMENTARY, 0, 1, 1 }, + new Object[] { STRING_SUPPLEMENTARY, 0, 2, 1 }, + new Object[] { STRING_SUPPLEMENTARY, 0, 3, 2 }, + new Object[] { STRING_SUPPLEMENTARY, 0, 5, 3 }, + new Object[] { STRING_SUPPLEMENTARY, 0, 6, 4 }, + new Object[] { STRING_SUPPLEMENTARY, 1, 4, 2 }, + new Object[] { STRING_SUPPLEMENTARY, 1, 6, 4 }, + new Object[] { STRING_SUPPLEMENTARY, 2, 4, 1 },}; + } + + @Test(dataProvider = "provider") + public void testCodePointCount(String str, int beginIndex, int endIndex, + int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.codePointCount(beginIndex, endIndex), + expected, + String.format( + "testing String(%s).codePointCount(%d, %d), source : %s, ", + escapeNonASCIIs(data), beginIndex, + endIndex, source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/CompactString.java b/jdk/test/java/lang/String/CompactString/CompactString.java new file mode 100644 index 0000000000000000000000000000000000000000..c22eacc1c0ff35080973bcad776da9bb6b2efac7 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/CompactString.java @@ -0,0 +1,307 @@ +/* + * 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.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +import org.testng.annotations.BeforeClass; + +/* + * Base class of tests for Compact String. + * + */ +public class CompactString { + + final Map<String, Map<String, String>> map = new HashMap<>(); + + enum StringSources { + EMPTY(STRING_EMPTY, BYTE_ARRAY_EMTPY, CHAR_ARRAY_EMPTY, + POINT_ARRAY_EMTPY), LDUPLICATE(STRING_LDUPLICATE, + BYTE_ARRAY_LDUPLICATE, CHAR_ARRAY_LDUPLICATE, + POINT_ARRAY_LDUPLICATE), LLONG(STRING_LLONG, BYTE_ARRAY_LLONG, + CHAR_ARRAY_LLONG, POINT_ARRAY_LLONG), L1(STRING_L1, + BYTE_ARRAY_L1, CHAR_ARRAY_L1, POINT_ARRAY_L1), L2(STRING_L2, + BYTE_ARRAY_L2, CHAR_ARRAY_L2, POINT_ARRAY_L2), L4(STRING_L4, + BYTE_ARRAY_L4, CHAR_ARRAY_L4, POINT_ARRAY_L4), UDUPLICATE( + STRING_UDUPLICATE, BYTE_ARRAY_UDUPLICATE, + CHAR_ARRAY_UDUPLICATE, POINT_ARRAY_UDUPLICATE), U1(STRING_U1, + BYTE_ARRAY_U1, CHAR_ARRAY_U1, POINT_ARRAY_U1), U2(STRING_U2, + BYTE_ARRAY_U2, CHAR_ARRAY_U2, POINT_ARRAY_U2), MDUPLICATE1( + STRING_MDUPLICATE1, BYTE_ARRAY_MDUPLICATE1, + CHAR_ARRAY_MDUPLICATE1, POINT_ARRAY_MDUPLICATE1), MDUPLICATE2( + STRING_MDUPLICATE2, BYTE_ARRAY_MDUPLICATE2, + CHAR_ARRAY_MDUPLICATE2, POINT_ARRAY_MDUPLICATE2), MLONG1( + STRING_MLONG1, BYTE_ARRAY_MLONG1, CHAR_ARRAY_MLONG1, + POINT_ARRAY_MLONG1), MLONG2(STRING_MLONG2, BYTE_ARRAY_MLONG2, + CHAR_ARRAY_MLONG2, POINT_ARRAY_MLONG2), M11(STRING_M11, + BYTE_ARRAY_M11, CHAR_ARRAY_M11, POINT_ARRAY_M11), M12( + STRING_M12, BYTE_ARRAY_M12, CHAR_ARRAY_M12, POINT_ARRAY_M12), SUPPLEMENTARY( + STRING_SUPPLEMENTARY, BYTE_ARRAY_SUPPLEMENTARY, + CHAR_ARRAY_SUPPLEMENTARY, POINT_ARRAY_SUPPLEMENTARY), SUPPLEMENTARY_LOWERCASE( + STRING_SUPPLEMENTARY_LOWERCASE, + BYTE_ARRAY_SUPPLEMENTARY_LOWERCASE, + CHAR_ARRAY_SUPPLEMENTARY_LOWERCASE, + POINT_ARRAY_SUPPLEMENTARY_LOWERCASE); + + private StringSources(String s, byte[] b, char[] c, int[] i) { + str = s; + ba = b; + ca = c; + ia = i; + } + + String getString() { + return str; + } + + byte[] getByteArray() { + return ba; + } + + char[] getCharArray() { + return ca; + } + + int[] getIntArray() { + return ia; + } + + private final String str; + private final byte[] ba; + private final char[] ca; + private final int[] ia; + } + + protected static final String DEFAULT_CHARSET_NAME = "UTF-8"; + protected static final Charset DEFAULT_CHARSET = Charset + .forName(DEFAULT_CHARSET_NAME); + + protected static final String STRING_EMPTY = ""; + protected static final byte[] BYTE_ARRAY_EMTPY = new byte[0]; + protected static final char[] CHAR_ARRAY_EMPTY = new char[0]; + protected static final int[] POINT_ARRAY_EMTPY = new int[0]; + + protected static final String STRING_LDUPLICATE = "ABABABABAB"; + protected static final byte[] BYTE_ARRAY_LDUPLICATE = new byte[] { 'A', 'B', + 'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' }; + protected static final char[] CHAR_ARRAY_LDUPLICATE = new char[] { 'A', 'B', + 'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' }; + protected static final int[] POINT_ARRAY_LDUPLICATE = new int[] { 'A', 'B', + 'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' }; + + protected static final String STRING_LLONG = "ABCDEFGH"; + protected static final byte[] BYTE_ARRAY_LLONG = new byte[] { 'A', 'B', 'C', + 'D', 'E', 'F', 'G', 'H' }; + protected static final char[] CHAR_ARRAY_LLONG = new char[] { 'A', 'B', 'C', + 'D', 'E', 'F', 'G', 'H' }; + protected static final int[] POINT_ARRAY_LLONG = new int[] { 'A', 'B', 'C', + 'D', 'E', 'F', 'G', 'H' }; + + protected static final String STRING_L1 = "A"; + protected static final byte[] BYTE_ARRAY_L1 = new byte[] { 'A' }; + protected static final char[] CHAR_ARRAY_L1 = new char[] { 'A' }; + protected static final int[] POINT_ARRAY_L1 = new int[] { 'A' }; + + protected static final String STRING_L2 = "AB"; + protected static final byte[] BYTE_ARRAY_L2 = new byte[] { 'A', 'B' }; + protected static final char[] CHAR_ARRAY_L2 = new char[] { 'A', 'B' }; + protected static final int[] POINT_ARRAY_L2 = new int[] { 'A', 'B' }; + + protected static final String STRING_L4 = "ABCD"; + protected static final byte[] BYTE_ARRAY_L4 = new byte[] { 'A', 'B', 'C', 'D' }; + protected static final char[] CHAR_ARRAY_L4 = new char[] { 'A', 'B', 'C', 'D' }; + protected static final int[] POINT_ARRAY_L4 = new int[] { 'A', 'B', 'C', 'D' }; + + /* + * Because right now ASCII is the default encoding parameter for source code + * in JDK build environment, so we escape them. same as below. + */ + protected static final String STRING_UDUPLICATE = "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22"; + protected static final byte[] BYTE_ARRAY_UDUPLICATE = getBytes(STRING_UDUPLICATE); + protected static final char[] CHAR_ARRAY_UDUPLICATE = new char[] { '\uFF21', + '\uFF22', '\uFF21', '\uFF22', '\uFF21', '\uFF22', '\uFF21', + '\uFF22', '\uFF21', '\uFF22' }; + protected static final int[] POINT_ARRAY_UDUPLICATE = new int[] { '\uFF21', + '\uFF22', '\uFF21', '\uFF22', '\uFF21', '\uFF22', '\uFF21', + '\uFF22', '\uFF21', '\uFF22' }; + + protected static final String STRING_U1 = "\uFF21"; + protected static final byte[] BYTE_ARRAY_U1 = getBytes(STRING_U1); + protected static final char[] CHAR_ARRAY_U1 = new char[] { '\uFF21' }; + protected static final int[] POINT_ARRAY_U1 = new int[] { '\uFF21' }; + + protected static final String STRING_U2 = "\uFF21\uFF22"; + protected static final byte[] BYTE_ARRAY_U2 = getBytes(STRING_U2); + protected static final char[] CHAR_ARRAY_U2 = new char[] { '\uFF21', '\uFF22' }; + protected static final int[] POINT_ARRAY_U2 = new int[] { '\uFF21', '\uFF22' }; + + protected static final String STRING_MDUPLICATE1 = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A"; + protected static final byte[] BYTE_ARRAY_MDUPLICATE1 = getBytes(STRING_MDUPLICATE1); + protected static final char[] CHAR_ARRAY_MDUPLICATE1 = new char[] { '\uFF21', + 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A' }; + protected static final int[] POINT_ARRAY_MDUPLICATE1 = new int[] { '\uFF21', + 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A' }; + + protected static final String STRING_MDUPLICATE2 = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21"; + protected static final byte[] BYTE_ARRAY_MDUPLICATE2 = getBytes(STRING_MDUPLICATE2); + protected static final char[] CHAR_ARRAY_MDUPLICATE2 = new char[] { 'A', + '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', + '\uFF21' }; + protected static final int[] POINT_ARRAY_MDUPLICATE2 = new int[] { 'A', + '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', + '\uFF21' }; + + protected static final String STRING_MLONG1 = "A\uFF21B\uFF22C\uFF23D\uFF24E\uFF25F\uFF26G\uFF27H\uFF28"; + protected static final byte[] BYTE_ARRAY_MLONG1 = getBytes(STRING_MLONG1); + protected static final char[] CHAR_ARRAY_MLONG1 = new char[] { 'A', '\uFF21', + 'B', '\uFF22', 'C', '\uFF23', 'D', '\uFF24', 'E', '\uFF25', 'F', + '\uFF26', 'G', '\uFF27', 'H', '\uFF28' }; + protected static final int[] POINT_ARRAY_MLONG1 = new int[] { 'A', '\uFF21', + 'B', '\uFF22', 'C', '\uFF23', 'D', '\uFF24', 'E', '\uFF25', 'F', + '\uFF26', 'G', '\uFF27', 'H', '\uFF28' }; + + protected static final String STRING_MLONG2 = "\uFF21A\uFF22B\uFF23C\uFF24D\uFF25E\uFF26F\uFF27G\uFF28H"; + protected static final byte[] BYTE_ARRAY_MLONG2 = getBytes(STRING_MLONG2); + protected static final char[] CHAR_ARRAY_MLONG2 = new char[] { '\uFF21', 'A', + '\uFF22', 'B', '\uFF23', 'C', '\uFF24', 'D', '\uFF25', 'E', + '\uFF26', 'F', '\uFF27', 'G', '\uFF28', 'H' }; + protected static final int[] POINT_ARRAY_MLONG2 = new int[] { '\uFF21', 'A', + '\uFF22', 'B', '\uFF23', 'C', '\uFF24', 'D', '\uFF25', 'E', + '\uFF26', 'F', '\uFF27', 'G', '\uFF28', 'H' }; + + protected static final String STRING_M11 = "A\uFF21"; + protected static final byte[] BYTE_ARRAY_M11 = getBytes(STRING_M11); + protected static final char[] CHAR_ARRAY_M11 = new char[] { 'A', '\uFF21' }; + protected static final int[] POINT_ARRAY_M11 = new int[] { 'A', '\uFF21' }; + + protected static final String STRING_M12 = "\uFF21A"; + protected static final byte[] BYTE_ARRAY_M12 = getBytes(STRING_M12); + protected static final char[] CHAR_ARRAY_M12 = new char[] { '\uFF21', 'A' }; + protected static final int[] POINT_ARRAY_M12 = new int[] { '\uFF21', 'A' }; + + protected static final String STRING_SUPPLEMENTARY = "\uD801\uDC00\uD801\uDC01\uFF21A"; + protected static final byte[] BYTE_ARRAY_SUPPLEMENTARY = getBytes(STRING_SUPPLEMENTARY); + protected static final char[] CHAR_ARRAY_SUPPLEMENTARY = new char[] { + '\uD801', '\uDC00', '\uD801', '\uDC01', '\uFF21', 'A' }; + protected static final int[] POINT_ARRAY_SUPPLEMENTARY = new int[] { + '\uD801', '\uDC00', '\uD801', '\uDC01', '\uFF21', 'A' }; + + protected static final String STRING_SUPPLEMENTARY_LOWERCASE = "\uD801\uDC28\uD801\uDC29\uFF41a"; + protected static final byte[] BYTE_ARRAY_SUPPLEMENTARY_LOWERCASE = getBytes(STRING_SUPPLEMENTARY_LOWERCASE); + protected static final char[] CHAR_ARRAY_SUPPLEMENTARY_LOWERCASE = new char[] { + '\uD801', '\uDC28', '\uD801', '\uDC29', '\uFF41', 'a' }; + protected static final int[] POINT_ARRAY_SUPPLEMENTARY_LOWERCASE = new int[] { + '\uD801', '\uDC28', '\uD801', '\uDC29', '\uFF41', 'a' }; + + protected static final String SRC_BYTE_ARRAY_WITH_CHARSETNAME = "source from byte array with charset name"; + protected static final String SRC_BYTE_ARRAY_WITH_CHARSET = "source from byte array with charset"; + protected static final String SRC_CHAR_ARRAY = "source from char array"; + protected static final String SRC_POINT_ARRAY = "source from code point array"; + protected static final String SRC_STRING = "source from String"; + protected static final String SRC_STRINGBUFFER = "source from StringBuffer"; + protected static final String SRC_STRINGBUILDER = "source from StringBuilder"; + protected static final String SRC_COPYVALUEOF = "source from copyValueOf from char array"; + protected static final String SRC_VALUEOF = "source from valueOf from char array"; + + static { + System.out + .println(String + .format("====== The platform's default charset is \"%s\", we're using \"%s\" for testing.", + Charset.defaultCharset().name(), + DEFAULT_CHARSET_NAME)); + } + + private static byte[] getBytes(String str) { + byte[] res = null; + try { + res = str.getBytes(DEFAULT_CHARSET_NAME); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + throw new RuntimeException("caught UnsupportedEncodingException!!!", e); + } + return res; + } + + private void setUpOneString(String content, byte[] ba, char[] ca, int[] cpa) + throws UnsupportedEncodingException { + final Map<String, String> m = new HashMap<>(); + m.put(SRC_BYTE_ARRAY_WITH_CHARSETNAME, new String(ba, + DEFAULT_CHARSET_NAME)); + m.put(SRC_BYTE_ARRAY_WITH_CHARSET, new String(ba, DEFAULT_CHARSET)); + m.put(SRC_CHAR_ARRAY, new String(ca)); + m.put(SRC_POINT_ARRAY, new String(cpa, 0, cpa.length)); + m.put(SRC_STRING, new String(content)); + m.put(SRC_STRINGBUFFER, new String(new StringBuffer(content))); + m.put(SRC_STRINGBUILDER, new String(new StringBuilder(content))); + m.put(SRC_COPYVALUEOF, String.copyValueOf(ca)); + m.put(SRC_VALUEOF, String.valueOf(ca)); + map.put(content, m); + } + + /* + * Set up the test data, use 9 ways to construct one String. + * + * @throws UnsupportedEncodingException + * If the named charset is not supported in setUpOneString(xxx). + */ + @BeforeClass + public void setUp() throws UnsupportedEncodingException { + for (StringSources src : StringSources.values()) { + setUpOneString(src.getString(), src.getByteArray(), + src.getCharArray(), src.getIntArray()); + } + } + + /* + * Because right now system default charset in JPRT environment is only + * guaranteed to support ASCII characters in log, so we escape them. + */ + protected String escapeNonASCIIs(String str) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c > 0x7F) { + sb.append("\\u").append(Integer.toHexString((int) c)); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + /* + * Because right now system default charset in JPRT environment is only + * guaranteed to support ASCII characters in log, so we escape them. + */ + protected String escapeNonASCII(char c) { + StringBuilder sb = new StringBuilder(); + if (c > 0x7F) { + sb.append("\\u").append(Integer.toHexString((int) c)); + } else { + sb.append(c); + } + return sb.toString(); + } +} diff --git a/jdk/test/java/lang/String/CompactString/CompareTo.java b/jdk/test/java/lang/String/CompactString/CompareTo.java new file mode 100644 index 0000000000000000000000000000000000000000..96f07cdf6103ec0352be67a0b06d260a3d1b6143 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/CompareTo.java @@ -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. + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.compareTo. + * @run testng/othervm -XX:+CompactStrings CompareTo + * @run testng/othervm -XX:-CompactStrings CompareTo + */ + +public class CompareTo extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "A", -1 }, + new Object[] { STRING_EMPTY, "\uFF21", -1 }, + new Object[] { STRING_L1, "AB", -1 }, + new Object[] { STRING_L1, "A", 0 }, + new Object[] { STRING_L1, "a", -32 }, + new Object[] { STRING_L1, "\uFF21", -65248 }, + new Object[] { STRING_L2, "AB", 0 }, + new Object[] { STRING_L2, "Ab", -32 }, + new Object[] { STRING_L2, "AA", 1 }, + new Object[] { STRING_L2, "\uFF21", -65248 }, + new Object[] { STRING_L2, "A\uFF21", -65247 }, + new Object[] { STRING_L4, "ABC", 1 }, + new Object[] { STRING_L4, "AB", 2 }, + new Object[] { STRING_L4, "ABcD", -32 }, + new Object[] { STRING_L4, "ABCD\uFF21\uFF21", -2 }, + new Object[] { STRING_L4, "ABCD\uFF21", -1 }, + new Object[] { STRING_LLONG, "ABCDEFG\uFF21", -65241 }, + new Object[] { STRING_LLONG, "AB", 6 }, + new Object[] { STRING_LLONG, "ABCD", 4 }, + new Object[] { STRING_LLONG, "ABCDEFGH\uFF21\uFF21", -2 }, + new Object[] { STRING_U1, "\uFF21", 0 }, + new Object[] { STRING_U1, "\uFF22", -1 }, + new Object[] { STRING_U1, "\uFF21\uFF22", -1 }, + new Object[] { STRING_U1, "A", 65248 }, + new Object[] { STRING_U2, "\uFF21\uFF22", 0 }, + new Object[] { STRING_U2, "\uFF22", -1 }, + new Object[] { STRING_U2, "\uFF21\uFF21", 1 }, + new Object[] { STRING_U2, "A", 65248 }, + new Object[] { STRING_M12, "\uFF21A", 0 }, + new Object[] { STRING_M12, "A\uFF21", 65248 }, + new Object[] { STRING_M12, "\uFF21\uFF21", -65248 }, + new Object[] { STRING_M11, "A\uFF21", 0 }, + new Object[] { STRING_M11, "\uFF21A", -65248 }, + new Object[] { STRING_M11, "AA", 65248 }, }; + } + + @Test(dataProvider = "provider") + public void testCompareTo(String str, String anotherString, int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.compareTo(anotherString), + expected, + String.format( + "testing String(%s).compareTo(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(anotherString), + source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/CompareToIgnoreCase.java b/jdk/test/java/lang/String/CompactString/CompareToIgnoreCase.java new file mode 100644 index 0000000000000000000000000000000000000000..3b9cef794c03523a088f74a0cdd4062d8baeb2f1 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/CompareToIgnoreCase.java @@ -0,0 +1,89 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.compareToIgnoreCase. + * @run testng/othervm -XX:+CompactStrings CompareToIgnoreCase + * @run testng/othervm -XX:-CompactStrings CompareToIgnoreCase + */ + +public class CompareToIgnoreCase extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "A", -1 }, + new Object[] { STRING_L1, "a", 0 }, + new Object[] { STRING_L1, "A", 0 }, + new Object[] { STRING_L1, "\uFF21", -65248 }, + new Object[] { STRING_L1, "B", -1 }, + new Object[] { STRING_L2, "AB", 0 }, + new Object[] { STRING_L2, "aB", 0 }, + new Object[] { STRING_L2, "\uFF21", -65248 }, + new Object[] { STRING_L2, "A\uFF21", -65247 }, + new Object[] { STRING_L4, "ABCD", 0 }, + new Object[] { STRING_L4, "abcd", 0 }, + new Object[] { STRING_L4, "ABc\uFF21", -65245 }, + new Object[] { STRING_LLONG, "ABCDEFGH", 0 }, + new Object[] { STRING_LLONG, "abcdefgh", 0 }, + new Object[] { STRING_LLONG, "ABCDEFG\uFF21", -65241 }, + new Object[] { STRING_LLONG, "abcdefg\uFF21", -65241 }, + new Object[] { STRING_U1, "\uFF41", 0 }, + new Object[] { STRING_U1, + "\uFF41\uFF42\uFF43\uFF44\uFF45\uFF46\uFF47\uFF48", -7 }, + new Object[] { STRING_U1, "A", 65248 }, + new Object[] { STRING_U2, "\uFF41", 1 }, + new Object[] { STRING_U2, "\uFF41\uFF42", 0 }, + new Object[] { STRING_U2, + "\uFF41\uFF42\uFF43\uFF44\uFF45\uFF46\uFF47\uFF48", -6 }, + new Object[] { STRING_M12, "\uFF41a", 0 }, + new Object[] { STRING_M12, "\uFF41\uFF42", -65249 }, + new Object[] { STRING_M11, "a\uFF41", 0 }, + new Object[] { STRING_M11, "a\uFF42", -1 }, }; + } + + @Test(dataProvider = "provider") + public void testCompareToIgnoreCase(String str, String anotherString, + int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.compareToIgnoreCase(anotherString), + expected, + String.format( + "testing String(%s).compareToIgnoreCase(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(anotherString), + source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/Concat.java b/jdk/test/java/lang/String/CompactString/Concat.java new file mode 100644 index 0000000000000000000000000000000000000000..de1238930c663c2040570d343fae432b7c4b72a5 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/Concat.java @@ -0,0 +1,132 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.concat. + * @run testng/othervm -XX:+CompactStrings Concat + * @run testng/othervm -XX:-CompactStrings Concat + */ + +public class Concat extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + new Object[] { STRING_EMPTY, "ABC", "ABC" }, + new Object[] { STRING_EMPTY, + "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"), + "ABC\uFF21\uFF22\uFF23DEF" }, + new Object[] { + STRING_EMPTY, + "\uFF21\uFF22\uFF23".concat("ABC").concat( + "\uFF24\uFF25\uFF26"), + "\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, + new Object[] { STRING_L1, + "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"), + "AABC\uFF21\uFF22\uFF23DEF" }, + new Object[] { + STRING_L1, + "\uFF21\uFF22\uFF23".concat("ABC").concat( + "\uFF24\uFF25\uFF26"), + "A\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, + new Object[] { STRING_L2, + "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"), + "ABABC\uFF21\uFF22\uFF23DEF" }, + new Object[] { + STRING_L2, + "\uFF21\uFF22\uFF23".concat("ABC").concat( + "\uFF24\uFF25\uFF26"), + "AB\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, + new Object[] { STRING_L4, + "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"), + "ABCDABC\uFF21\uFF22\uFF23DEF" }, + new Object[] { + STRING_L4, + "\uFF21\uFF22\uFF23".concat("ABC").concat( + "\uFF24\uFF25\uFF26"), + "ABCD\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, + new Object[] { STRING_LLONG, + "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"), + "ABCDEFGHABC\uFF21\uFF22\uFF23DEF" }, + new Object[] { + STRING_LLONG, + "\uFF21\uFF22\uFF23".concat("ABC").concat( + "\uFF24\uFF25\uFF26"), + "ABCDEFGH\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, + new Object[] { STRING_U1, + "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"), + "\uFF21ABC\uFF21\uFF22\uFF23DEF" }, + new Object[] { + STRING_U1, + "\uFF21\uFF22\uFF23".concat("ABC").concat( + "\uFF24\uFF25\uFF26"), + "\uFF21\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, + new Object[] { STRING_U2, + "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"), + "\uFF21\uFF22ABC\uFF21\uFF22\uFF23DEF" }, + new Object[] { + STRING_U2, + "\uFF21\uFF22\uFF23".concat("ABC").concat( + "\uFF24\uFF25\uFF26"), + "\uFF21\uFF22\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, + new Object[] { STRING_M12, + "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"), + "\uFF21AABC\uFF21\uFF22\uFF23DEF" }, + new Object[] { + STRING_M12, + "\uFF21\uFF22\uFF23".concat("ABC").concat( + "\uFF24\uFF25\uFF26"), + "\uFF21A\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, + new Object[] { STRING_M11, + "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"), + "A\uFF21ABC\uFF21\uFF22\uFF23DEF" }, + new Object[] { + STRING_M11, + "\uFF21\uFF22\uFF23".concat("ABC").concat( + "\uFF24\uFF25\uFF26"), + "A\uFF21\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, }; + } + + @Test(dataProvider = "provider") + public void testConcat(String str, String anotherString, String expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.concat(anotherString), + expected, + String.format( + "testing String(%s).concat(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(anotherString), + source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/Contains.java b/jdk/test/java/lang/String/CompactString/Contains.java new file mode 100644 index 0000000000000000000000000000000000000000..ad182b8212e4e8adc4c9354f7dfe60eeabb1dc98 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/Contains.java @@ -0,0 +1,91 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.contains. + * @run testng/othervm -XX:+CompactStrings Contains + * @run testng/othervm -XX:-CompactStrings Contains + */ + +public class Contains extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "", true }, + new Object[] { STRING_EMPTY, "A", false }, + new Object[] { STRING_EMPTY, "\uFF21", false }, + new Object[] { STRING_L1, "", true }, + new Object[] { STRING_L1, "A", true }, + new Object[] { STRING_L1, "\uFF21", false }, + new Object[] { STRING_L2, "", true }, + new Object[] { STRING_L2, "A", true }, + new Object[] { STRING_L2, "AB", true }, + new Object[] { STRING_L2, "B", true }, + new Object[] { STRING_L2, "ABC", false }, + new Object[] { STRING_L2, "ab", false }, + new Object[] { STRING_L4, "ABCD", true }, + new Object[] { STRING_L4, "BC", true }, + new Object[] { STRING_LLONG, "ABCDEFGH", true }, + new Object[] { STRING_LLONG, "BCDEFGH", true }, + new Object[] { STRING_LLONG, "EF", true }, + new Object[] { STRING_U1, "", true }, + new Object[] { STRING_U1, "\uFF21", true }, + new Object[] { STRING_U1, "a", false }, + new Object[] { STRING_U1, "\uFF21B", false }, + new Object[] { STRING_U2, "", true }, + new Object[] { STRING_U2, "\uFF21\uFF22", true }, + new Object[] { STRING_U2, "a", false }, + new Object[] { STRING_U2, "\uFF21B", false }, + new Object[] { STRING_M12, "\uFF21A", true }, + new Object[] { STRING_M12, "\uFF21", true }, + new Object[] { STRING_M12, "A", true }, + new Object[] { STRING_M12, "A\uFF21", false }, + new Object[] { STRING_M11, "A\uFF21", true }, + new Object[] { STRING_M11, "Ab", false }, }; + } + + @Test(dataProvider = "provider") + public void testContains(String str, String anotherString, boolean expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.contains(anotherString), + expected, + String.format( + "testing String(%s).contains(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(anotherString), + source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/EndsWith.java b/jdk/test/java/lang/String/CompactString/EndsWith.java new file mode 100644 index 0000000000000000000000000000000000000000..07485b4eb71c1f80c0c9b54e16b395d339d2a33d --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/EndsWith.java @@ -0,0 +1,92 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.endsWith. + * @run testng/othervm -XX:+CompactStrings EndsWith + * @run testng/othervm -XX:-CompactStrings EndsWith + */ + +public class EndsWith extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { new Object[] { STRING_EMPTY, "", true }, + new Object[] { STRING_EMPTY, "A", false }, + new Object[] { STRING_L1, "A", true }, + new Object[] { STRING_L1, "", true }, + new Object[] { STRING_L1, " ", false }, + new Object[] { STRING_L2, "AB", true }, + new Object[] { STRING_L2, "B", true }, + new Object[] { STRING_L2, "", true }, + new Object[] { STRING_L2, "A", false }, + new Object[] { STRING_L4, "ABCD", true }, + new Object[] { STRING_L4, "CD", true }, + new Object[] { STRING_L4, "D", true }, + new Object[] { STRING_L4, "", true }, + new Object[] { STRING_L4, "BC", false }, + new Object[] { STRING_LLONG, "ABCDEFGH", true }, + new Object[] { STRING_LLONG, "EFGH", true }, + new Object[] { STRING_LLONG, "", true }, + new Object[] { STRING_LLONG, "CDEF", false }, + new Object[] { STRING_LLONG, "\uFF28", false }, + new Object[] { STRING_U1, "\uFF21", true }, + new Object[] { STRING_U1, "", true }, + new Object[] { STRING_U1, "\uFF22", false }, + new Object[] { STRING_U1, "B", false }, + new Object[] { STRING_U2, "\uFF21\uFF22", true }, + new Object[] { STRING_U2, "\uFF22", true }, + new Object[] { STRING_U2, "", true }, + new Object[] { STRING_U2, "\uFF21", false }, + new Object[] { STRING_M12, "\uFF21A", true }, + new Object[] { STRING_M12, "A", true }, + new Object[] { STRING_M12, "", true }, + new Object[] { STRING_M12, "AA", false }, + new Object[] { STRING_M11, "A\uFF21", true }, + new Object[] { STRING_M11, "\uFF21", true }, + new Object[] { STRING_M11, "", true }, + new Object[] { STRING_M11, "\uFF21\uFF21", false }, }; + } + + @Test(dataProvider = "provider") + public void testEndsWith(String str, String suffix, boolean expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.endsWith(suffix), + expected, + String.format( + "testing String(%s).endsWith(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(suffix), source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/Equals.java b/jdk/test/java/lang/String/CompactString/Equals.java new file mode 100644 index 0000000000000000000000000000000000000000..101a015b4008a89931a8e73402c889e6c5be7ea5 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/Equals.java @@ -0,0 +1,81 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.equals. + * @run testng/othervm -XX:+CompactStrings Equals + * @run testng/othervm -XX:-CompactStrings Equals + */ + +public class Equals extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + new Object[] { STRING_EMPTY, "", true }, + new Object[] { STRING_EMPTY, "A", false }, + new Object[] { STRING_EMPTY, new StringBuffer(""), false }, + new Object[] { STRING_L1, "A", true }, + new Object[] { STRING_L1, "", false }, + new Object[] { STRING_L1, new StringBuffer("A"), false }, + new Object[] { STRING_L2, "AB", true }, + new Object[] { STRING_L2, "", false }, + new Object[] { STRING_L2, new StringBuilder("AB"), false }, + new Object[] { STRING_L4, "ABCD", true }, + new Object[] { STRING_L4, "abc", false }, + new Object[] { STRING_L4, "", false }, + new Object[] { STRING_LLONG, "ABCDEFGH", true }, + new Object[] { STRING_LLONG, "ABCDEFG", false }, + new Object[] { STRING_LLONG, new StringBuilder("ABCDEFGH"), + false }, + new Object[] { STRING_U1, "\uFF21", true }, + new Object[] { STRING_U1, "", false }, + new Object[] { STRING_U2, "\uFF21\uFF22", true }, + new Object[] { STRING_U2, "\uFF21", false }, + new Object[] { STRING_U2, "", false }, + new Object[] { STRING_U2, new StringBuilder("\uFF21\uFF22"), + false }, + new Object[] { STRING_M12, "\uFF21A", true }, + new Object[] { STRING_M12, "A\uFF21", false }, + new Object[] { STRING_M11, "A\uFF21", true }, + new Object[] { STRING_M11, new StringBuilder("\uFF21A"), false }, }; + } + + @Test(dataProvider = "provider") + public void testEquals(String str, Object obj, boolean expected) { + map.get(str).forEach( + (source, data) -> { + assertEquals(data.equals(obj), expected, String.format( + "testing String(%s).equals(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(obj.toString()), source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/EqualsIgnoreCase.java b/jdk/test/java/lang/String/CompactString/EqualsIgnoreCase.java new file mode 100644 index 0000000000000000000000000000000000000000..0721c07b617233cb403e28a9a250d5ad06107e65 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/EqualsIgnoreCase.java @@ -0,0 +1,77 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.equalsIgnoreCase. + * @run testng/othervm -XX:+CompactStrings EqualsIgnoreCase + * @run testng/othervm -XX:-CompactStrings EqualsIgnoreCase + */ + +public class EqualsIgnoreCase extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "", true }, + new Object[] { STRING_L1, "a", true }, + new Object[] { STRING_L2, "aB", true }, + new Object[] { STRING_L4, "AbCd", true }, + new Object[] { STRING_LLONG, "aBcDeFgH", true }, + new Object[] { STRING_U1, "\uFF41", true }, + new Object[] { STRING_U1, "\uFF21", true }, + new Object[] { STRING_U2, "\uFF41\uFF42", true }, + new Object[] { STRING_U2, "\uFF41\uFF22", true }, + new Object[] { STRING_U2, "\uFF21\uFF42", true }, + new Object[] { STRING_M12, "\uFF41a", true }, + new Object[] { STRING_M12, "\uFF21A", true }, + new Object[] { STRING_M11, "a\uFF41", true }, + new Object[] { STRING_M11, "A\uFF21", true }, + + }; + } + + @Test(dataProvider = "provider") + public void testEqualsIgnoreCase(String str, String anotherString, + boolean expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.equalsIgnoreCase(anotherString), + expected, + String.format( + "testing String(%s).equalsIgnoreCase(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(anotherString), + source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/GetChars.java b/jdk/test/java/lang/String/CompactString/GetChars.java new file mode 100644 index 0000000000000000000000000000000000000000..3ea3dce956680207b4852866d9bdf0e69b3c2837 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/GetChars.java @@ -0,0 +1,91 @@ +/* + * 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.util.Arrays; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.getChars. + * @run testng/othervm -XX:+CompactStrings GetChars + * @run testng/othervm -XX:-CompactStrings GetChars + */ + +public class GetChars extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, 0, STRING_EMPTY.length(), + new char[STRING_EMPTY.length()], 0, CHAR_ARRAY_EMPTY }, + new Object[] { STRING_L1, 0, STRING_L1.length(), + new char[STRING_L1.length()], 0, CHAR_ARRAY_L1 }, + new Object[] { STRING_L2, 0, STRING_L2.length(), + new char[STRING_L2.length()], 0, CHAR_ARRAY_L2 }, + new Object[] { STRING_L4, 0, STRING_L4.length(), + new char[STRING_L4.length()], 0, CHAR_ARRAY_L4 }, + new Object[] { STRING_LLONG, 0, STRING_LLONG.length(), + new char[STRING_LLONG.length()], 0, CHAR_ARRAY_LLONG }, + new Object[] { STRING_U1, 0, STRING_U1.length(), + new char[STRING_U1.length()], 0, CHAR_ARRAY_U1 }, + new Object[] { STRING_U2, 0, STRING_U2.length(), + new char[STRING_U2.length()], 0, CHAR_ARRAY_U2 }, + new Object[] { STRING_M12, 0, STRING_M12.length(), + new char[STRING_M12.length()], 0, CHAR_ARRAY_M12 }, + new Object[] { STRING_M11, 0, STRING_M11.length(), + new char[STRING_M11.length()], 0, CHAR_ARRAY_M11 }, + new Object[] { STRING_UDUPLICATE, 0, + STRING_UDUPLICATE.length(), + new char[STRING_UDUPLICATE.length()], 0, + CHAR_ARRAY_UDUPLICATE }, + new Object[] { STRING_MDUPLICATE1, 0, + STRING_MDUPLICATE1.length(), + new char[STRING_MDUPLICATE1.length()], 0, + CHAR_ARRAY_MDUPLICATE1 }, }; + } + + @Test(dataProvider = "provider") + public void testGetChars(String str, int srcBegin, int srcEnd, char[] dst, + int dstBegin, char[] expected) { + map.get(str) + .forEach( + (source, data) -> { + data.getChars(srcBegin, srcEnd, dst, dstBegin); + assertTrue( + Arrays.equals(dst, expected), + String.format( + "testing String(%s).getChars(%d, %d, %s, %d), source : %s, ", + escapeNonASCIIs(data), srcBegin, + srcEnd, escapeNonASCIIs(Arrays + .toString(dst)), dstBegin, + source)); + }); + } + +} diff --git a/jdk/test/java/lang/String/CompactString/IndexOf.java b/jdk/test/java/lang/String/CompactString/IndexOf.java new file mode 100644 index 0000000000000000000000000000000000000000..49fd9e54d055626dd63bd8a69aec854a5b1dbe43 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/IndexOf.java @@ -0,0 +1,249 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.indexOf. + * @run testng/othervm -XX:+CompactStrings IndexOf + * @run testng/othervm -XX:-CompactStrings IndexOf + */ + +public class IndexOf extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, (int) 'A', -1 }, + new Object[] { STRING_L1, (int) 'A', 0 }, + new Object[] { STRING_L2, (int) 'A', 0 }, + new Object[] { STRING_L2, (int) 'B', 1 }, + new Object[] { STRING_L4, (int) 'A', 0 }, + new Object[] { STRING_L4, (int) 'D', 3 }, + new Object[] { STRING_L4, (int) 'E', -1 }, + new Object[] { STRING_LLONG, (int) 'A', 0 }, + new Object[] { STRING_LLONG, (int) 'H', 7 }, + new Object[] { STRING_U1, (int) '\uFF21', 0 }, + new Object[] { STRING_U1, (int) 'A', -1 }, + new Object[] { STRING_U2, (int) '\uFF21', 0 }, + new Object[] { STRING_U2, (int) '\uFF22', 1 }, + new Object[] { STRING_M12, (int) '\uFF21', 0 }, + new Object[] { STRING_M12, (int) 'A', 1 }, + new Object[] { STRING_M11, (int) 'A', 0 }, + new Object[] { STRING_M11, (int) '\uFF21', 1 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 0 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 1 }, + new Object[] { STRING_SUPPLEMENTARY, 'A', 5 }, + new Object[] { STRING_SUPPLEMENTARY, '\uFF21', 4 }, + new Object[] { STRING_SUPPLEMENTARY, + Character.toCodePoint('\uD801', '\uDC00'), 0 }, + new Object[] { STRING_SUPPLEMENTARY, + Character.toCodePoint('\uD801', '\uDC01'), 2 }, }; + } + + @Test(dataProvider = "provider") + public void testIndexOf(String str, int ch, int expected) { + map.get(str).forEach( + (source, data) -> { + assertEquals(data.indexOf(ch), expected, String.format( + "testing String(%s).indexOf(%d), source : %s, ", + escapeNonASCIIs(data), ch, source)); + }); + } + + @DataProvider + public Object[][] provider2() { + return new Object[][] { + + new Object[] { STRING_EMPTY, (int) 'A', 0, -1 }, + new Object[] { STRING_L1, (int) 'A', 0, 0 }, + new Object[] { STRING_L1, (int) 'A', 1, -1 }, + new Object[] { STRING_L1, (int) 'B', 0, -1 }, + new Object[] { STRING_L2, (int) 'A', 0, 0 }, + new Object[] { STRING_L2, (int) 'A', 1, -1 }, + new Object[] { STRING_L2, (int) 'B', 0, 1 }, + new Object[] { STRING_L2, (int) 'B', 1, 1 }, + new Object[] { STRING_L4, (int) 'A', 0, 0 }, + new Object[] { STRING_L4, (int) 'D', 2, 3 }, + new Object[] { STRING_L4, (int) 'B', 2, -1 }, + new Object[] { STRING_LLONG, (int) 'A', 0, 0 }, + new Object[] { STRING_LLONG, (int) 'H', 5, 7 }, + new Object[] { STRING_U1, (int) '\uFF21', 0, 0 }, + new Object[] { STRING_U1, (int) 'A', 0, -1 }, + new Object[] { STRING_U2, (int) '\uFF21', 0, 0 }, + new Object[] { STRING_U2, (int) '\uFF22', 0, 1 }, + new Object[] { STRING_M12, (int) '\uFF21', 0, 0 }, + new Object[] { STRING_M12, (int) 'A', 1, 1 }, + new Object[] { STRING_M11, (int) 'A', 0, 0 }, + new Object[] { STRING_M11, (int) '\uFF21', 1, 1 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 1, 2 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 1, 1 }, }; + } + + @Test(dataProvider = "provider2") + public void testIndexOf(String str, int ch, int fromIndex, int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.indexOf(ch, fromIndex), + expected, + String.format( + "testing String(%s).indexOf(%d, %d), source : %s, ", + escapeNonASCIIs(data), ch, + fromIndex, source)); + }); + } + + @DataProvider + public Object[][] provider3() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "A", -1 }, + new Object[] { STRING_L1, "A", 0 }, + new Object[] { STRING_L1, "AB", -1 }, + new Object[] { STRING_L2, "A", 0 }, + new Object[] { STRING_L2, "B", 1 }, + new Object[] { STRING_L2, "AB", 0 }, + new Object[] { STRING_L2, "AC", -1 }, + new Object[] { STRING_L2, "ABC", -1 }, + new Object[] { STRING_L4, "ABCD", 0 }, + new Object[] { STRING_L4, "D", 3 }, + new Object[] { STRING_LLONG, "ABCDEFGH", 0 }, + new Object[] { STRING_LLONG, "EFGH", 4 }, + new Object[] { STRING_LLONG, "EFGHI", -1 }, + new Object[] { STRING_U1, "\uFF21", 0 }, + new Object[] { STRING_U1, "\uFF21A", -1 }, + new Object[] { STRING_U2, "\uFF21\uFF22", 0 }, + new Object[] { STRING_U2, "\uFF22", 1 }, + new Object[] { STRING_U2, "A\uFF22", -1 }, + new Object[] { STRING_M12, "\uFF21A", 0 }, + new Object[] { STRING_M12, "A", 1 }, + new Object[] { STRING_M12, "\uFF21\uFF21", -1 }, + new Object[] { STRING_M11, "A\uFF21", 0 }, + new Object[] { STRING_M11, "\uFF21", 1 }, + new Object[] { STRING_M11, "A", 0 }, + new Object[] { + STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", + 0 }, + new Object[] { STRING_UDUPLICATE, + "\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21", 1 }, + new Object[] { + STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21", + -1 }, }; + } + + @Test(dataProvider = "provider3") + public void testIndexOf(String str, String anotherString, int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.indexOf(anotherString), + expected, + String.format( + "testing String(%s).indexOf(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(anotherString), + source)); + }); + } + + @DataProvider + public Object[][] provider4() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "A", 0, -1 }, + new Object[] { STRING_L1, "A", 0, 0 }, + new Object[] { STRING_L1, "A", 1, -1 }, + new Object[] { STRING_L1, "AB", 0, -1 }, + new Object[] { STRING_L2, "A", 0, 0 }, + new Object[] { STRING_L2, "B", 0, 1 }, + new Object[] { STRING_L2, "AB", 0, 0 }, + new Object[] { STRING_L2, "AB", 1, -1 }, + new Object[] { STRING_L4, "ABCD", 0, 0 }, + new Object[] { STRING_L4, "BC", 0, 1 }, + new Object[] { STRING_L4, "A", 0, 0 }, + new Object[] { STRING_L4, "CD", 0, 2 }, + new Object[] { STRING_L4, "A", 2, -1 }, + new Object[] { STRING_L4, "ABCDE", 0, -1 }, + new Object[] { STRING_LLONG, "ABCDEFGH", 0, 0 }, + new Object[] { STRING_LLONG, "DEFGH", 0, 3 }, + new Object[] { STRING_LLONG, "A", 0, 0 }, + new Object[] { STRING_LLONG, "GHI", 0, -1 }, + new Object[] { STRING_U1, "\uFF21", 0, 0 }, + new Object[] { STRING_U1, "\uFF21A", 0, -1 }, + new Object[] { STRING_U2, "\uFF21\uFF22", 0, 0 }, + new Object[] { STRING_U2, "\uFF22", 0, 1 }, + new Object[] { STRING_U2, "\uFF21", 1, -1 }, + new Object[] { STRING_M12, "\uFF21A", 0, 0 }, + new Object[] { STRING_M12, "A", 1, 1 }, + new Object[] { STRING_M12, "\uFF21A", 1, -1 }, + new Object[] { STRING_M12, "\uFF21", 0, 0 }, + new Object[] { STRING_M11, "A\uFF21", 0, 0 }, + new Object[] { STRING_M11, "\uFF21", 1, 1 }, + new Object[] { STRING_M11, "A\uFF21", 1, -1 }, + new Object[] { STRING_M11, "A\uFF21A", 0, -1 }, + new Object[] { + STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", + 0, 0 }, + new Object[] { + STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", + 1, -1 }, + new Object[] { + STRING_UDUPLICATE, + "\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", + 1, 1 }, + new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22", + 4, 4 }, + new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22", + 7, -1 }, }; + } + + @Test(dataProvider = "provider4") + public void testIndexOf(String str, String anotherString, int fromIndex, + int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.indexOf(anotherString, fromIndex), + expected, + String.format( + "testing String(%s).indexOf(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(anotherString), + fromIndex, source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/Intern.java b/jdk/test/java/lang/String/CompactString/Intern.java new file mode 100644 index 0000000000000000000000000000000000000000..fc2b06d29ebfd6b43d5c0695a35333a071337a7e --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/Intern.java @@ -0,0 +1,64 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.intern. + * @run testng/othervm -XX:+CompactStrings Intern + * @run testng/othervm -XX:-CompactStrings Intern + */ + +public class Intern extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "" }, + new Object[] { STRING_L1, "A" }, + new Object[] { STRING_LLONG, "ABCDEFGH" }, + new Object[] { STRING_U1, "\uFF21" }, + new Object[] { STRING_U2, "\uFF21\uFF22" }, + new Object[] { STRING_M12, "\uFF21A" }, + new Object[] { STRING_M11, "A\uFF21" }, + new Object[] { STRING_MDUPLICATE1, + "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" }, }; + } + + @Test(dataProvider = "provider") + public void testIntern(String str, String expected) { + map.get(str).forEach( + (source, data) -> { + assertTrue(data.intern() == expected, String.format( + "testing String(%s).intern(), source : %s, ", + escapeNonASCIIs(data), source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/LastIndexOf.java b/jdk/test/java/lang/String/CompactString/LastIndexOf.java new file mode 100644 index 0000000000000000000000000000000000000000..eccc9cc41adecacea06ab7d5a5e32eaa1edc82f7 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/LastIndexOf.java @@ -0,0 +1,225 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.lastIndexOf. + * @run testng/othervm -XX:+CompactStrings LastIndexOf + * @run testng/othervm -XX:-CompactStrings LastIndexOf + */ + +public class LastIndexOf extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, (int) 'A', -1 }, + new Object[] { STRING_L1, (int) 'A', 0 }, + new Object[] { STRING_L2, (int) 'A', 0 }, + new Object[] { STRING_L2, (int) 'B', 1 }, + new Object[] { STRING_L4, (int) 'A', 0 }, + new Object[] { STRING_L4, (int) 'D', 3 }, + new Object[] { STRING_LLONG, (int) 'A', 0 }, + new Object[] { STRING_LLONG, (int) 'H', 7 }, + new Object[] { STRING_U1, (int) '\uFF21', 0 }, + new Object[] { STRING_U1, (int) 'B', -1 }, + new Object[] { STRING_U2, (int) '\uFF21', 0 }, + new Object[] { STRING_U2, (int) '\uFF22', 1 }, + new Object[] { STRING_M12, (int) '\uFF21', 0 }, + new Object[] { STRING_M12, (int) 'A', 1 }, + new Object[] { STRING_M11, (int) 'A', 0 }, + new Object[] { STRING_M11, (int) '\uFF21', 1 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 9 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 8 }, + new Object[] { STRING_SUPPLEMENTARY, + Character.toCodePoint('\uD801', '\uDC01'), 2 }, }; + } + + @Test(dataProvider = "provider") + public void testLastIndexOf(String str, int ch, int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.lastIndexOf(ch), + expected, + String.format( + "testing String(%s).lastIndexOf(%d), source : %s, ", + escapeNonASCIIs(data), ch, source)); + }); + } + + @DataProvider + public Object[][] provider2() { + return new Object[][] { + + new Object[] { STRING_EMPTY, (int) 'A', 0, -1 }, + new Object[] { STRING_L1, (int) 'A', 0, 0 }, + new Object[] { STRING_L1, (int) 'A', 1, 0 }, + new Object[] { STRING_L2, (int) 'A', 0, 0 }, + new Object[] { STRING_L2, (int) 'B', 1, 1 }, + new Object[] { STRING_L2, (int) 'B', 2, 1 }, + new Object[] { STRING_L4, (int) 'A', 0, 0 }, + new Object[] { STRING_L4, (int) 'C', 2, 2 }, + new Object[] { STRING_L4, (int) 'C', 1, -1 }, + new Object[] { STRING_LLONG, (int) 'A', 0, 0 }, + new Object[] { STRING_LLONG, (int) 'H', 7, 7 }, + new Object[] { STRING_LLONG, (int) 'H', 6, -1 }, + new Object[] { STRING_U1, (int) '\uFF21', 0, 0 }, + new Object[] { STRING_U1, (int) '\uFF21', 7, 0 }, + new Object[] { STRING_U2, (int) '\uFF21', 0, 0 }, + new Object[] { STRING_U2, (int) '\uFF22', 0, -1 }, + new Object[] { STRING_M12, (int) '\uFF21', 0, 0 }, + new Object[] { STRING_M12, (int) 'A', 1, 1 }, + new Object[] { STRING_M12, (int) 'A', 0, -1 }, + new Object[] { STRING_M11, (int) 'A', 0, 0 }, + new Object[] { STRING_M11, (int) '\uFF21', 1, 1 }, + new Object[] { STRING_M11, (int) '\uFF21', 0, -1 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 5, 4 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 6, 6 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 5, 5 }, + new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 6, 5 }, }; + } + + @Test(dataProvider = "provider2") + public void testLastIndexOf(String str, int ch, int fromIndex, int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.lastIndexOf(ch, fromIndex), + expected, + String.format( + "testing String(%s).lastIndexOf(%d, %d), source : %s, ", + escapeNonASCIIs(data), ch, + fromIndex, source)); + }); + } + + @DataProvider + public Object[][] provider3() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "A", -1 }, + new Object[] { STRING_L1, "A", 0 }, + new Object[] { STRING_L1, "AB", -1 }, + + new Object[] { STRING_L2, "AB", 0 }, + new Object[] { STRING_L2, "B", 1 }, + new Object[] { STRING_L4, "ABCD", 0 }, + new Object[] { STRING_L4, "B", 1 }, + new Object[] { STRING_LLONG, "ABCD", 0 }, + new Object[] { STRING_LLONG, "GH", 6 }, + new Object[] { STRING_U1, "\uFF21", 0 }, + new Object[] { STRING_U1, "\uFF22", -1 }, + new Object[] { STRING_U2, "\uFF21\uFF22", 0 }, + new Object[] { STRING_U2, "\uFF22", 1 }, + new Object[] { STRING_M12, "\uFF21A", 0 }, + new Object[] { STRING_M12, "A", 1 }, + new Object[] { STRING_M11, "A\uFF21", 0 }, + new Object[] { STRING_M11, "\uFF21", 1 }, + new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22", 6 }, + new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", 8 }, }; + } + + @Test(dataProvider = "provider3") + public void testLastIndexOf(String str, String anotherString, int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.lastIndexOf(anotherString), + expected, + String.format( + "testing String(%s).lastIndexOf(%s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(anotherString), + source)); + }); + } + + @DataProvider + public Object[][] provider4() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "A", 0, -1 }, + new Object[] { STRING_L2, "AB", 0, 0 }, + + new Object[] { STRING_L1, "AB", -1, -1 }, + + new Object[] { STRING_L2, "B", 1, 1 }, + new Object[] { STRING_L2, "B", 0, -1 }, + new Object[] { STRING_L4, "ABC", 3, 0 }, + new Object[] { STRING_L4, "ABC", 0, 0 }, + new Object[] { STRING_L4, "ABC", 1, 0 }, + new Object[] { STRING_L4, "BC", 1, 1 }, + new Object[] { STRING_L4, "BC", 0, -1 }, + new Object[] { STRING_LLONG, "ABCDEFGH", 0, 0 }, + new Object[] { STRING_LLONG, "EFGH", 7, 4 }, + new Object[] { STRING_LLONG, "EFGH", 3, -1 }, + new Object[] { STRING_U1, "\uFF21", 0, 0 }, + new Object[] { STRING_U1, "\uFF21", 7, 0 }, + new Object[] { STRING_U2, "\uFF21\uFF22", 0, 0 }, + new Object[] { STRING_U2, "\uFF21\uFF22", 1, 0 }, + new Object[] { STRING_M12, "\uFF21A", 0, 0 }, + new Object[] { STRING_M12, "A", 1, 1 }, + new Object[] { STRING_M12, "A", 0, -1 }, + new Object[] { STRING_M11, "A\uFF21", 0, 0 }, + new Object[] { STRING_M11, "A\uFF21", 1, 0 }, + new Object[] { STRING_M11, "\uFF21", 0, -1 }, + new Object[] { + STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", + 9, 0 }, + new Object[] { + STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", + 0, 0 }, + new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", 6, 6 }, + new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21", 6, 6 }, }; + } + + @Test(dataProvider = "provider4") + public void testLastIndexOf(String str, String anotherString, + int fromIndex, int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.lastIndexOf(anotherString, fromIndex), + expected, + String.format( + "testing String(%s).lastIndexOf(%s, %d), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(anotherString), + fromIndex, source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/Length.java b/jdk/test/java/lang/String/CompactString/Length.java new file mode 100644 index 0000000000000000000000000000000000000000..ab2b9d5508249b883846cbecb8da91a293f7d984 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/Length.java @@ -0,0 +1,61 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.length. + * @run testng/othervm -XX:+CompactStrings Length + * @run testng/othervm -XX:-CompactStrings Length + */ + +public class Length extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, 0 }, new Object[] { STRING_L1, 1 }, + new Object[] { STRING_L2, 2 }, + new Object[] { STRING_LLONG, 8 }, + new Object[] { STRING_U1, 1 }, new Object[] { STRING_U2, 2 }, + new Object[] { STRING_M12, 2 }, new Object[] { STRING_M11, 2 }, + new Object[] { STRING_UDUPLICATE, 10 }, + new Object[] { STRING_SUPPLEMENTARY, 6 }, }; + } + + @Test(dataProvider = "provider") + public void testLength(String str, int expected) { + map.get(str).forEach( + (source, data) -> { + assertEquals(data.length(), expected, String.format( + "testing String(%s).length(), source : %s, ", + escapeNonASCIIs(data), source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/Numbers.java b/jdk/test/java/lang/String/CompactString/Numbers.java new file mode 100644 index 0000000000000000000000000000000000000000..ad9f17aaaceeab9455e9f0853a0e451a615361e0 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/Numbers.java @@ -0,0 +1,106 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is testing + * Integer/Long's methods related to String. + * @run testng/othervm -XX:+CompactStrings Numbers + * @run testng/othervm -XX:-CompactStrings Numbers + */ + +public class Numbers { + + /* + * Data provider for testIntegerLong + * + * @return input parameter for testIntegerLong + */ + @DataProvider + public Object[][] numbers() { + return new Object[][] { + { Integer.toBinaryString(Integer.MAX_VALUE), + "1111111111111111111111111111111" }, + { Integer.toBinaryString(Integer.MIN_VALUE), + "10000000000000000000000000000000" }, + { Integer.toBinaryString(7), "111" }, + { Integer.toBinaryString(0), "0" }, + { Integer.toOctalString(Integer.MAX_VALUE), "17777777777" }, + { Integer.toOctalString(Integer.MIN_VALUE), "20000000000" }, + { Integer.toOctalString(9), "11" }, + { Integer.toOctalString(0), "0" }, + { Integer.toHexString(Integer.MAX_VALUE), "7fffffff" }, + { Integer.toHexString(Integer.MIN_VALUE), "80000000" }, + { Integer.toHexString(17), "11" }, + { Integer.toHexString(0), "0" }, + { Integer.toString(Integer.MAX_VALUE, 2), + "1111111111111111111111111111111" }, + { Integer.toString(Integer.MIN_VALUE, 2), + "-10000000000000000000000000000000" }, + { Integer.toString(7, 2), "111" }, + { Integer.toString(0, 2), "0" }, + { Integer.toString(Integer.MAX_VALUE, 8), "17777777777" }, + { Integer.toString(Integer.MIN_VALUE, 8), "-20000000000" }, + { Integer.toString(9, 8), "11" }, + { Integer.toString(Integer.MAX_VALUE, 16), "7fffffff" }, + { Integer.toString(Integer.MIN_VALUE, 16), "-80000000" }, + { Integer.toString(17, 16), "11" }, + { Long.toBinaryString(Long.MAX_VALUE), + "111111111111111111111111111111111111111111111111111111111111111" }, + { Long.toBinaryString(Long.MIN_VALUE), + "1000000000000000000000000000000000000000000000000000000000000000" }, + { Long.toOctalString(Long.MAX_VALUE), "777777777777777777777" }, + { Long.toOctalString(Long.MIN_VALUE), "1000000000000000000000" }, + { Long.toHexString(Long.MAX_VALUE), "7fffffffffffffff" }, + { Long.toHexString(Long.MIN_VALUE), "8000000000000000" }, + { Long.toString(Long.MAX_VALUE, 2), + "111111111111111111111111111111111111111111111111111111111111111" }, + { Long.toString(Long.MIN_VALUE, 2), + "-1000000000000000000000000000000000000000000000000000000000000000" }, + { Long.toString(Long.MAX_VALUE, 8), "777777777777777777777" }, + { Long.toString(Long.MIN_VALUE, 8), "-1000000000000000000000" }, + { Long.toString(Long.MAX_VALUE, 16), "7fffffffffffffff" }, + { Long.toString(Long.MIN_VALUE, 16), "-8000000000000000" } }; + } + + /* + * test Integer/Long's methods related to String. + * + * @param res + * real result + * @param expected + * expected result + */ + @Test(dataProvider = "numbers") + public void testIntegerLong(String res, String expected) { + assertEquals(res, expected); + } + +} diff --git a/jdk/test/java/lang/String/CompactString/OffsetByCodePoints.java b/jdk/test/java/lang/String/CompactString/OffsetByCodePoints.java new file mode 100644 index 0000000000000000000000000000000000000000..44ed6071db79695bb5e47ae612aa13cc24d451b0 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/OffsetByCodePoints.java @@ -0,0 +1,71 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.offsetByCodePoints. + * @run testng/othervm -XX:+CompactStrings OffsetByCodePoints + * @run testng/othervm -XX:-CompactStrings OffsetByCodePoints + */ + +public class OffsetByCodePoints extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_SUPPLEMENTARY, 0, 1, 2 }, + new Object[] { STRING_SUPPLEMENTARY, 0, 3, 5 }, + new Object[] { STRING_SUPPLEMENTARY, 1, 1, 2 }, + new Object[] { STRING_SUPPLEMENTARY, 1, 3, 5 }, + new Object[] { STRING_SUPPLEMENTARY, 2, 1, 4 }, + new Object[] { STRING_SUPPLEMENTARY, 2, 2, 5 }, + new Object[] { STRING_SUPPLEMENTARY, 2, 3, 6 }, + new Object[] { STRING_SUPPLEMENTARY, 3, 1, 4 }, + new Object[] { STRING_SUPPLEMENTARY, 3, 2, 5 }, + new Object[] { STRING_SUPPLEMENTARY, 3, 3, 6 }, }; + } + + @Test(dataProvider = "provider") + public void testOffsetByCodePoints(String str, int index, + int codePointOffset, int expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.offsetByCodePoints(index, + codePointOffset), + expected, + String.format( + "testing String(%s).offsetByCodePoints(%d, %d), source : %s, ", + escapeNonASCIIs(data), index, + codePointOffset, source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/RegionMatches.java b/jdk/test/java/lang/String/CompactString/RegionMatches.java new file mode 100644 index 0000000000000000000000000000000000000000..5301c0eef3104306fe062a80f0e9d1d2c828e6b0 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/RegionMatches.java @@ -0,0 +1,105 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.regionMatches. + * @run testng/othervm -XX:+CompactStrings RegionMatches + * @run testng/othervm -XX:-CompactStrings RegionMatches + */ + +public class RegionMatches extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, true, 0, "", 0, 0, true }, + new Object[] { STRING_EMPTY, true, 0, "", 0, 1, false }, + new Object[] { STRING_EMPTY, true, 0, "A", 0, 0, true }, + new Object[] { STRING_EMPTY, true, 0, "", 0, 0, true }, + new Object[] { STRING_EMPTY, true, 0, "", 0, 1, false }, + new Object[] { STRING_L1, false, 0, "a", 0, 1, false }, + new Object[] { STRING_L1, false, 0, "BA", 1, 1, true }, + new Object[] { STRING_L1, false, 0, "Ba", 1, 1, false }, + new Object[] { STRING_L1, true, 0, "a", 0, 1, true }, + new Object[] { STRING_L1, true, 0, "BA", 1, 1, true }, + new Object[] { STRING_L1, true, 0, "Ba", 1, 1, true }, + new Object[] { STRING_L2, true, 1, "b", 0, 1, true }, + new Object[] { STRING_L2, true, 1, "B", 0, 1, true }, + new Object[] { STRING_L2, true, 0, "xaBc", 1, 2, true }, + new Object[] { STRING_L2, false, 0, "AB", 0, 2, true }, + new Object[] { STRING_L2, false, 0, "Ab", 0, 2, false }, + new Object[] { STRING_L2, false, 1, "BAB", 2, 1, true }, + new Object[] { STRING_LLONG, true, 1, "bCdEF", 0, 5, true }, + new Object[] { STRING_LLONG, false, 2, "CDEFG", 0, 5, true }, + new Object[] { STRING_LLONG, true, 2, "CDEFg", 0, 5, true }, + new Object[] { STRING_U1, true, 0, "\uFF41", 0, 1, true }, + new Object[] { STRING_U1, false, 0, "\uFF41", 0, 1, false }, + new Object[] { STRING_MDUPLICATE1, true, 0, "\uFF41a\uFF41", 0, + 3, true }, + new Object[] { STRING_MDUPLICATE1, false, 0, "\uFF21a\uFF21", + 0, 3, false }, + new Object[] { STRING_SUPPLEMENTARY, true, 1, "\uDC00\uD801", + 0, 2, true }, + new Object[] { STRING_SUPPLEMENTARY, true, 4, "\uFF21", 0, 1, + true }, + new Object[] { STRING_SUPPLEMENTARY, true, 5, "A", 0, 1, true }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 0, + "\uD801\uDC28\uD801\uDC29", 0, 4, true }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 1, + "\uDC28\uD801", 0, 2, true }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 1, + "\uDC00\uD801", 0, 2, false }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 4, + "\uFF21", 0, 1, true }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 4, + "\uFF21", 0, 1, false }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 4, + "\uFF41", 0, 1, true }, }; + } + + @Test(dataProvider = "provider") + public void testRegionMatches(String str, boolean ignoreCase, int toffset, + String other, int ooffset, int len, boolean expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.regionMatches(ignoreCase, toffset, + other, ooffset, len), + expected, + String.format( + "testing String(%s).regionMatches(%b, %d, %s, %d, %d), source : %s, ", + escapeNonASCIIs(data), ignoreCase, + toffset, escapeNonASCIIs(other), + ooffset, len, source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/Replace.java b/jdk/test/java/lang/String/CompactString/Replace.java new file mode 100644 index 0000000000000000000000000000000000000000..95540f15152b9e7c29bdc2c4ef84ec8976f16b3e --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/Replace.java @@ -0,0 +1,117 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.replace. + * @run testng/othervm -XX:+CompactStrings Replace + * @run testng/othervm -XX:-CompactStrings Replace + */ + +public class Replace extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_L1, 'A', 'B', "B" }, + new Object[] { STRING_L1, 'A', 'A', "A" }, + new Object[] { STRING_L1, 'A', '\uFF21', "\uFF21" }, + new Object[] { STRING_L2, 'A', 'B', "BB" }, + new Object[] { STRING_L2, 'B', 'A', "AA" }, + new Object[] { STRING_L2, 'C', 'A', "AB" }, + new Object[] { STRING_L2, 'B', '\uFF21', "A\uFF21" }, + new Object[] { STRING_U1, '\uFF21', 'A', "A" }, + new Object[] { STRING_U1, '\uFF22', 'A', "\uFF21" }, + new Object[] { STRING_U2, '\uFF22', 'A', "\uFF21A" }, + new Object[] { STRING_M12, 'A', '\uFF21', "\uFF21\uFF21" }, + new Object[] { STRING_M11, '\uFF21', 'A', "AA" }, + new Object[] { STRING_UDUPLICATE, '\uFF21', 'A', + "A\uFF22A\uFF22A\uFF22A\uFF22A\uFF22" }, + new Object[] { STRING_MDUPLICATE1, '\uFF21', 'A', "AAAAAAAAAA" }, + new Object[] { STRING_MDUPLICATE1, 'A', '\uFF21', + "\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21" }, }; + } + + @Test(dataProvider = "provider") + public void testReplace(String str, char oldChar, char newChar, + String expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.replace(oldChar, newChar), + expected, + String.format( + "testing String(%s).replace(%s, %s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCII(oldChar), + escapeNonASCII(newChar), source)); + }); + } + + @DataProvider + public Object[][] provider2() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "", "ABC", "ABC" }, + new Object[] { STRING_EMPTY, "", "", "" }, + new Object[] { STRING_L1, "A", "B", "B" }, + new Object[] { STRING_L1, "A", "A", "A" }, + new Object[] { STRING_L2, "B", "\uFF21", "A\uFF21" }, + new Object[] { STRING_LLONG, "BCD", "\uFF21", "A\uFF21EFGH" }, + new Object[] { STRING_U1, "\uFF21", "A", "A" }, + new Object[] { STRING_U1, "\uFF21", "A\uFF21", "A\uFF21" }, + new Object[] { STRING_U2, "\uFF21", "A", "A\uFF22" }, + new Object[] { STRING_U2, "\uFF22", "A", "\uFF21A" }, + new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", "AB", + "ABABABABAB" }, + new Object[] { STRING_MDUPLICATE1, "\uFF21", "A", "AAAAAAAAAA" }, + new Object[] { STRING_MDUPLICATE1, "A", "\uFF21", + "\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21" }, }; + } + + @Test(dataProvider = "provider2") + public void testReplace(String str, CharSequence target, + CharSequence replacement, String expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.replace(target, replacement), + expected, + String.format( + "testing String(%s).replace(%s, %s), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(target.toString()), + escapeNonASCIIs(replacement + .toString()), source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/SerializationTest.java b/jdk/test/java/lang/String/CompactString/SerializationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e4c94c573ba9389328b908b516b364f058f7deb0 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/SerializationTest.java @@ -0,0 +1,89 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static jdk.testlibrary.SerializationUtils.*; +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @library /lib/testlibrary + * @build jdk.testlibrary.SerializationUtils + * @summary Tests Compact String. This one is testing String serialization + * among -XX:+CompactStrings/-XX:-CompactStrings/LegacyString + * @run testng/othervm -XX:+CompactStrings SerializationTest + * @run testng/othervm -XX:-CompactStrings SerializationTest + */ + +public class SerializationTest { + @DataProvider + public Object[][] provider() { + return new Object[][] { + // every byte array is serialized from corresponding String object + // by previous JDK(build 1.8.0_45-b14). + new Object[] { "", new byte[] { -84, -19, 0, 5, 116, 0, 0 } }, + new Object[] { "A", new byte[] { -84, -19, 0, 5, 116, 0, 1, 65 } }, + new Object[] { "AB", new byte[] { -84, -19, 0, 5, 116, 0, 2, 65, 66 } }, + new Object[] { "abcdefghijk", + new byte[] {-84, -19, 0, 5, 116, 0, 11, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107 } }, + new Object[] { "\uff21", new byte[] { -84, -19, 0, 5, 116, 0, 3, -17, -68, -95 } }, + new Object[] { "\uff21\uff22", new byte[] { -84, -19, 0, 5, 116, 0, 6, -17, -68, + -95, -17, -68, -94 } }, + new Object[] { "\uff21A\uff21A\uff21A\uff21A\uff21A", + new byte[] { -84, -19, 0, 5, 116, 0, 20, -17, -68, -95, 65, -17, -68, + -95, 65, -17, -68, -95, 65, -17, -68, -95, 65, -17, -68, -95, 65 } }, + new Object[] { "A\uff21B\uff22C\uff23D\uff24E\uff25F\uff26G\uff27H\uff28", + new byte[] { -84, -19, 0, 5, 116, 0, 32, 65, -17, -68, -95, 66, -17, -68, + -94, 67, -17, -68, -93, 68, -17, -68, -92, 69, -17, -68, -91, 70, -17, + -68, -90, 71, -17, -68, -89, 72, -17, -68, -88 } }, + new Object[] { "\uff21A\uff22B\uff23C\uff24D\uff25E\uff26F\uff27G\uff28H", + new byte[] { -84, -19, 0, 5, 116, 0, 32, -17, -68, -95, 65, -17, -68, + -94, 66, -17, -68, -93, 67, -17, -68, -92, 68, -17, -68, -91, 69, -17, + -68, -90, 70, -17, -68, -89, 71, -17, -68, -88, 72 } }, + new Object[] { "\ud801\udc00\ud801\udc01\uff21A", + new byte[] { -84, -19, 0, 5, 116, 0, 16, -19, -96, -127, -19, -80, -128, + -19, -96, -127, -19, -80, -127, -17, -68, -95, 65 } }, + new Object[] { "\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22", + new byte[] { -84, -19, 0, 5, 116, 0, 30, -17, -68, -95, -17, -68, -94, -17, + -68, -95, -17, -68, -94, -17, -68, -95, -17, -68, -94, -17, -68, -95, -17, + -68, -94, -17, -68, -95, -17, -68, -94 } } }; + } + + /* + * Verify serialization works between Compact String/Legacy String + */ + @Test(dataProvider = "provider") + public void test(String strContent, byte[] baInJDK8) throws Exception { + // Serialize a String object into byte array. + byte[] ba = serialize(strContent); + assertEquals(ba, baInJDK8); + // Deserialize a String object from byte array which is generated by previous JDK(build 1.8.0_45-b14). + Object obj = deserialize(ba); + assertEquals(obj.getClass(), String.class); + assertEquals((String)obj, strContent); + } +} diff --git a/jdk/test/java/lang/String/CompactString/Split.java b/jdk/test/java/lang/String/CompactString/Split.java new file mode 100644 index 0000000000000000000000000000000000000000..2707ae34edf013eb3e803dfd9886d28ec72a6cfe --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/Split.java @@ -0,0 +1,181 @@ +/* + * 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.util.Arrays; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.split. + * @run testng/othervm -XX:+CompactStrings Split + * @run testng/othervm -XX:-CompactStrings Split + */ + +public class Split extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + new Object[] { STRING_L1, "", 0, new String[] { "A" } }, + new Object[] { STRING_L1, "", 1, new String[] { "A" } }, + new Object[] { STRING_L1, "", 2, new String[] { "A", "" } }, + new Object[] { STRING_L1, "A", 0, new String[] {} }, + new Object[] { STRING_L2, "A", 0, new String[] { "", "B" } }, + new Object[] { STRING_L2, "B", 0, new String[] { "A" } }, + new Object[] { STRING_LLONG, "D", 0, + new String[] { "ABC", "EFGH" } }, + new Object[] { STRING_LLONG, "[D]", 0, + new String[] { "ABC", "EFGH" } }, + new Object[] { STRING_LLONG, "CD", 0, + new String[] { "AB", "EFGH" } }, + new Object[] { STRING_LLONG, "DC", 0, + new String[] { "ABCDEFGH" } }, + new Object[] { STRING_LLONG, "[CF]", 0, + new String[] { "AB", "DE", "GH" } }, + new Object[] { STRING_LLONG, "[CF]", 1, + new String[] { "ABCDEFGH" } }, + new Object[] { STRING_LLONG, "[CF]", 2, + new String[] { "AB", "DEFGH" } }, + new Object[] { STRING_LLONG, "[FC]", 0, + new String[] { "AB", "DE", "GH" } }, + new Object[] { STRING_LLONG, "[FC]", 1, + new String[] { "ABCDEFGH" } }, + new Object[] { STRING_LLONG, "[FC]", 2, + new String[] { "AB", "DEFGH" } }, + new Object[] { STRING_U1, "", 0, new String[] { "\uFF21" } }, + new Object[] { STRING_U1, "", 1, new String[] { "\uFF21" } }, + new Object[] { STRING_U1, "", 2, new String[] { "\uFF21", "" } }, + new Object[] { STRING_U1, "\uFF21", 0, new String[] {} }, + new Object[] { STRING_M12, "\uFF21", 0, + new String[] { "", "A" } }, + new Object[] { STRING_M12, "A", 0, new String[] { "\uFF21" } }, + new Object[] { + STRING_UDUPLICATE, + "\uFF21", + 0, + new String[] { "", "\uFF22", "\uFF22", "\uFF22", + "\uFF22", "\uFF22" } }, + new Object[] { + STRING_UDUPLICATE, + "\uFF21", + 2, + new String[] { "", + "\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22" } }, + new Object[] { + STRING_UDUPLICATE, + "\uFF21", + 4, + new String[] { "", "\uFF22", "\uFF22", + "\uFF22\uFF21\uFF22\uFF21\uFF22" } }, + new Object[] { + STRING_UDUPLICATE, + "\uFF22", + 0, + new String[] { "\uFF21", "\uFF21", "\uFF21", "\uFF21", + "\uFF21" } }, + new Object[] { + STRING_UDUPLICATE, + "\uFF22", + 3, + new String[] { "\uFF21", "\uFF21", + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22" } }, + + new Object[] { STRING_MDUPLICATE1, "\uFF21", 0, + new String[] { "", "A", "A", "A", "A", "A" } }, + new Object[] { STRING_MDUPLICATE1, "\uFF21", 3, + new String[] { "", "A", "A\uFF21A\uFF21A\uFF21A" } }, + new Object[] { + STRING_MDUPLICATE1, + "A", + 0, + new String[] { "\uFF21", "\uFF21", "\uFF21", "\uFF21", + "\uFF21" } }, + new Object[] { + STRING_MDUPLICATE1, + "A", + 4, + new String[] { "\uFF21", "\uFF21", "\uFF21", + "\uFF21A\uFF21A" } }, + new Object[] { STRING_SUPPLEMENTARY, "\uD801\uDC01", 0, + new String[] { "\uD801\uDC00", "\uFF21A" } }, + new Object[] { STRING_SUPPLEMENTARY, "\uDC01", 0, + new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } }, + new Object[] { STRING_SUPPLEMENTARY, "\uD801\uDC01", 0, + new String[] { "\uD801\uDC00", "\uFF21A" } }, + new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 0, + new String[] { "\uD801\uDC00", "", "A" } }, + new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 1, + new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } }, + new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 2, + new String[] { "\uD801\uDC00", "\uFF21A" } }, + new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 0, + new String[] { "\uD801\uDC00", "", "A" } }, + new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 1, + new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } }, + new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 2, + new String[] { "\uD801\uDC00", "\uFF21A" } }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, "\uDC01", 0, + new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, "\uD801\uDC29", + 0, new String[] { "\uD801\uDC28", "\uFF41a" } }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, + "[\uD801\uDC29\uFF41]", 0, + new String[] { "\uD801\uDC28", "", "a" } }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, + "[\uD801\uDC29\uFF41]", 1, + new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, + "[\uD801\uDC29\uFF41]", 2, + new String[] { "\uD801\uDC28", "\uFF41a" } }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, + "[\uFF41\uD801\uDC29]", 0, + new String[] { "\uD801\uDC28", "", "a" } }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, + "[\uFF41\uD801\uDC29]", 1, + new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, + "[\uFF41\uD801\uDC29]", 2, + new String[] { "\uD801\uDC28", "\uFF41a" } }, }; + } + + @Test(dataProvider = "provider") + public void testSplit(String str, String regex, int limit, String[] expected) { + map.get(str) + .forEach( + (source, data) -> { + assertTrue( + Arrays.equals(data.split(regex, limit), + expected), + String.format( + "testing String(%s).split(%s, %d), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(regex), limit, + source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/StartsWith.java b/jdk/test/java/lang/String/CompactString/StartsWith.java new file mode 100644 index 0000000000000000000000000000000000000000..97109bb1529e48053ea01abc18b5a95d7758a348 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/StartsWith.java @@ -0,0 +1,109 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.startsWith. + * @run testng/othervm -XX:+CompactStrings StartsWith + * @run testng/othervm -XX:-CompactStrings StartsWith + */ + +public class StartsWith extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + new Object[] {STRING_EMPTY, "", 0, true}, + new Object[] {STRING_EMPTY, "A", 0, false}, + new Object[] {STRING_EMPTY, "", 0, true}, + new Object[] {STRING_EMPTY, "", -1, false}, + new Object[] {STRING_L1, "A", 0, true}, + new Object[] {STRING_L1, "A", -1, false}, + new Object[] {STRING_L1, "A", 1, false}, + new Object[] {STRING_L2, "B", 1, true}, + new Object[] {STRING_L2, "B", 0, false}, + new Object[] {STRING_L2, "A", 0, true}, + new Object[] {STRING_L2, "AB", 1, false}, + new Object[] {STRING_L4, "ABC", 0, true}, + new Object[] {STRING_LLONG, "ABCDEFGH", 0, true}, + new Object[] {STRING_LLONG, "ABCDE", 0, true}, + new Object[] {STRING_LLONG, "CDE", 0, false}, + new Object[] {STRING_LLONG, "FG", 5, true}, + new Object[] {STRING_U1, "\uFF21", 0, true}, + new Object[] {STRING_U1, "", 1, true}, + new Object[] {STRING_U1, "\uFF21", 0, true}, + new Object[] {STRING_U1, "A", 0, false}, + new Object[] {STRING_U2, "\uFF21\uFF22", 0, true}, + new Object[] {STRING_U2, "\uFF21", 0, true}, + new Object[] {STRING_U2, "\uFF22", 0, false}, + new Object[] {STRING_U2, "", 0, true}, + new Object[] {STRING_M12, "\uFF21", 0, true}, + new Object[] {STRING_M12, "\uFF21A", 0, true}, + new Object[] {STRING_M12, "A", 0, false}, + new Object[] {STRING_M12, "\uFF21A", 0, true}, + new Object[] {STRING_M12, "A", 1, true}, + new Object[] {STRING_M11, "A", 0, true}, + new Object[] {STRING_M11, "A\uFF21", 0, true}, + new Object[] {STRING_M11, "A\uFF21", 0, true}, + new Object[] {STRING_M11, "\uFF21", 1, true}, + new Object[] {STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", + 0, true}, + new Object[] {STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 0, true}, + new Object[] {STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 2, true}, + new Object[] {STRING_UDUPLICATE, + "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 5, false}, + new Object[] {STRING_MDUPLICATE1, + "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A", 0, true}, + new Object[] {STRING_MDUPLICATE1, + "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21", 0, true}, + new Object[] {STRING_MDUPLICATE1, "A\uFF21A\uFF21A\uFF21A", 1, true}, + new Object[] {STRING_SUPPLEMENTARY, "\uDC01\uFF21", 3, true}, + }; + } + + @Test(dataProvider = "provider") + public void testStartsWith(String str, String prefix, int toffset, + boolean expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.startsWith(prefix, toffset), + expected, + String.format( + "testing String(%s).startsWith(%s, %d), source : %s, ", + escapeNonASCIIs(data), + escapeNonASCIIs(prefix), toffset, + source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/SubString.java b/jdk/test/java/lang/String/CompactString/SubString.java new file mode 100644 index 0000000000000000000000000000000000000000..f34f16168b57ff9d39ebd13f8ddc796550c8a1c2 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/SubString.java @@ -0,0 +1,84 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.subString. + * @run testng/othervm -XX:+CompactStrings SubString + * @run testng/othervm -XX:-CompactStrings SubString + */ + +public class SubString extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, 0, 0, "" }, + new Object[] { STRING_L1, 0, 1, "A" }, + new Object[] { STRING_L1, 1, 1, "" }, + new Object[] { STRING_L2, 0, 2, "AB" }, + new Object[] { STRING_L2, 1, 2, "B" }, + new Object[] { STRING_LLONG, 0, 8, "ABCDEFGH" }, + new Object[] { STRING_LLONG, 7, 8, "H" }, + new Object[] { STRING_LLONG, 8, 8, "" }, + new Object[] { STRING_LLONG, 3, 7, "DEFG" }, + new Object[] { STRING_U1, 0, 1, "\uFF21" }, + new Object[] { STRING_U1, 1, 1, "" }, + new Object[] { STRING_U1, 0, 0, "" }, + new Object[] { STRING_U2, 0, 2, "\uFF21\uFF22" }, + new Object[] { STRING_U2, 1, 2, "\uFF22" }, + new Object[] { STRING_U2, 2, 2, "" }, + new Object[] { STRING_U2, 0, 2, "\uFF21\uFF22" }, + new Object[] { STRING_U2, 1, 2, "\uFF22" }, + new Object[] { STRING_M12, 1, 2, "A" }, + new Object[] { STRING_M11, 0, 1, "A" }, + new Object[] { STRING_M11, 1, 2, "\uFF21" }, + new Object[] { STRING_UDUPLICATE, 1, 5, + "\uFF22\uFF21\uFF22\uFF21" }, + new Object[] { STRING_MDUPLICATE1, 9, 10, "A" }, + new Object[] { STRING_MDUPLICATE1, 7, 8, "A" }, }; + } + + @Test(dataProvider = "provider") + public void testSubstring(String str, int beginIndex, int endIndex, + String expected) { + map.get(str) + .forEach( + (source, data) -> { + assertEquals( + data.substring(beginIndex, endIndex), + expected, + String.format( + "testing String(%s).substring(%d, %d), source : %s, ", + escapeNonASCIIs(data), beginIndex, + endIndex, source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/ToCharArray.java b/jdk/test/java/lang/String/CompactString/ToCharArray.java new file mode 100644 index 0000000000000000000000000000000000000000..bf7dbdefd57434fb7425d51dc699050d419ce14e --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/ToCharArray.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 java.util.Arrays; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.toCharArray. + * @run testng/othervm -XX:+CompactStrings ToCharArray + * @run testng/othervm -XX:-CompactStrings ToCharArray + */ + +public class ToCharArray extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + new Object[] { STRING_EMPTY, new char[] {} }, + new Object[] { STRING_L1, new char[] { 'A' } }, + new Object[] { STRING_L2, new char[] { 'A', 'B' } }, + new Object[] { STRING_LLONG, + new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } }, + new Object[] { STRING_U1, new char[] { '\uFF21' } }, + new Object[] { STRING_U2, new char[] { '\uFF21', '\uFF22' } }, + new Object[] { STRING_M12, new char[] { '\uFF21', 'A' } }, + new Object[] { STRING_M11, new char[] { 'A', '\uFF21' } }, }; + } + + @Test(dataProvider = "provider") + public void testToCharArray(String str, char[] expected) { + map.get(str) + .forEach( + (source, data) -> { + assertTrue( + Arrays.equals(data.toCharArray(), expected), + String.format( + "testing String(%s).toCharArray(), source : %s, ", + escapeNonASCIIs(data), source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/ToLowerCase.java b/jdk/test/java/lang/String/CompactString/ToLowerCase.java new file mode 100644 index 0000000000000000000000000000000000000000..aa49aadbfca32f6f280eaf764abb93f137043597 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/ToLowerCase.java @@ -0,0 +1,66 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.toLowerCase. + * @run testng/othervm -XX:+CompactStrings ToLowerCase + * @run testng/othervm -XX:-CompactStrings ToLowerCase + */ + +public class ToLowerCase extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + new Object[] { STRING_EMPTY, "" }, + new Object[] { STRING_L1, "a" }, + new Object[] { STRING_L2, "ab" }, + new Object[] { STRING_U1, "\uFF41" }, + new Object[] { STRING_MDUPLICATE1, + "\uFF41a\uFF41a\uFF41a\uFF41a\uFF41a" }, + new Object[] { STRING_SUPPLEMENTARY, + "\uD801\uDC28\uD801\uDC29\uFF41a" }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, + "\uD801\uDC28\uD801\uDC29\uFF41a" }, + new Object[] { STRING_SUPPLEMENTARY, + STRING_SUPPLEMENTARY_LOWERCASE } }; + } + + @Test(dataProvider = "provider") + public void testToLowerCase(String str, String expected) { + map.get(str).forEach( + (source, data) -> { + assertEquals(data.toLowerCase(), expected, String.format( + "testing String(%s).toLowerCase(), source : %s, ", + escapeNonASCIIs(data), source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/ToUpperCase.java b/jdk/test/java/lang/String/CompactString/ToUpperCase.java new file mode 100644 index 0000000000000000000000000000000000000000..d3eced31104e961ecf007ed6b01271f5472025c5 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/ToUpperCase.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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.toUpperCase. + * @run testng/othervm -XX:+CompactStrings ToUpperCase + * @run testng/othervm -XX:-CompactStrings ToUpperCase + */ + +public class ToUpperCase extends CompactString { + + @DataProvider + public Object[][] provider() { + return new Object[][] { + + new Object[] { STRING_EMPTY, "" }, + new Object[] { STRING_L1, "A" }, + new Object[] { STRING_L2, "AB" }, + new Object[] { STRING_U1, "\uFF21" }, + new Object[] { STRING_MDUPLICATE1, + "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" }, + new Object[] { STRING_SUPPLEMENTARY, + "\uD801\uDC00\uD801\uDC01\uFF21A" }, + + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, + "\uD801\uDC00\uD801\uDC01\uFF21A" }, + new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, + STRING_SUPPLEMENTARY }, }; + } + + @Test(dataProvider = "provider") + public void testToUpperCase(String str, String expected) { + map.get(str).forEach( + (source, data) -> { + assertEquals(data.toUpperCase(), expected, String.format( + "testing String(%s).toUpperCase(), source : %s, ", + escapeNonASCIIs(data), source)); + }); + } +} diff --git a/jdk/test/java/lang/String/CompactString/Trim.java b/jdk/test/java/lang/String/CompactString/Trim.java new file mode 100644 index 0000000000000000000000000000000000000000..03d0f9fce1acc9c152ba1ea30caf15dc1be2b2e0 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/Trim.java @@ -0,0 +1,71 @@ +/* + * 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 org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.trim. + * @run testng/othervm -XX:+CompactStrings Trim + * @run testng/othervm -XX:-CompactStrings Trim + */ + +public class Trim { + + /* + * Data provider for testTrim + * + * @return input parameter for testTrim + */ + @DataProvider + public Object[][] trims() { + return new Object[][] { + { " \t \t".trim(), "" }, + { "\t \t ".trim(), "" }, + { "\t A B C\t ".trim(), "A B C" }, + { " \t A B C \t".trim(), "A B C" }, + { "\t \uFF21 \uFF22 \uFF23\t ".trim(), "\uFF21 \uFF22 \uFF23" }, + { " \t \uFF21 \uFF22 \uFF23 \t".trim(), "\uFF21 \uFF22 \uFF23" }, + { " \t \uFF41 \uFF42 \uFF43 \t".trim(), "\uFF41 \uFF42 \uFF43" }, + { " \t A\uFF21 B\uFF22 C\uFF23 \t".trim(), + "A\uFF21 B\uFF22 C\uFF23" } }; + } + + /* + * test trim(). + * + * @param res + * real result + * @param expected + * expected result + */ + @Test(dataProvider = "trims") + public void testTrim(String res, String expected) { + assertEquals(res, expected); + } + +} diff --git a/jdk/test/java/lang/String/CompactString/VMOptionsTest.java b/jdk/test/java/lang/String/CompactString/VMOptionsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..01eed446292f762809f92629c1cf60c89b5b203d --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/VMOptionsTest.java @@ -0,0 +1,91 @@ +/* + * 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.io.*; +import java.lang.reflect.Field; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is testing + * if Compact String enable/disable VM Options is indeed working in String class, + * it's verified by testing if the VM option affect coder and + * COMPACT_STRINGS field in String class. + * @run testng/othervm -XX:+CompactStrings -DCompactStringEnabled=true VMOptionsTest + * @run testng/othervm -XX:-CompactStrings -DCompactStringEnabled=false VMOptionsTest + */ + +public class VMOptionsTest { + boolean compactStringEnabled; + // corresponding "COMPACT_STRINGS" field in String class. + Field COMPACT_STRINGS; + // corresponding "coder" field in String class. + Field coder; + + // corresponding coder type in String class. + final byte LATIN1 = 0; + final byte UTF16 = 1; + + @BeforeClass + public void setUp() throws Exception { + compactStringEnabled = Boolean.valueOf(System.getProperty("CompactStringEnabled", null)); + COMPACT_STRINGS = String.class.getDeclaredField("COMPACT_STRINGS"); + COMPACT_STRINGS.setAccessible(true); + coder = String.class.getDeclaredField("coder"); + coder.setAccessible(true); + } + + @DataProvider + public Object[][] provider() { + return new Object[][] { + new Object[] {"", LATIN1}, + new Object[] {"abc", LATIN1}, + new Object[] {"A\uff21", UTF16}, + new Object[] {"\uff21\uff22", UTF16} + }; + } + + /* + * verify the coder field in String objects. + */ + @Test(dataProvider = "provider") + public void testCoder(String str, byte expected) throws Exception { + byte c = (byte) coder.get(str); + expected = compactStringEnabled ? expected : UTF16; + assertEquals(c, expected); + } + + /* + * verify the COMPACT_STRINGS flag in String objects. + */ + @Test(dataProvider = "provider") + public void testCompactStringFlag(String str, byte ignore) throws Exception { + assertTrue(COMPACT_STRINGS.get(str).equals(compactStringEnabled)); + } +} diff --git a/jdk/test/java/lang/String/CompactString/ValueOf.java b/jdk/test/java/lang/String/CompactString/ValueOf.java new file mode 100644 index 0000000000000000000000000000000000000000..cf47416c6f12fd7b375d92a9752082bae6f5a4b1 --- /dev/null +++ b/jdk/test/java/lang/String/CompactString/ValueOf.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. + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This one is for String.valueOf. + * valueOf(char[] data) is not tested here. + * @run testng/othervm -XX:+CompactStrings ValueOf + * @run testng/othervm -XX:-CompactStrings ValueOf + */ + +public class ValueOf { + + /* + * Data provider for testValueOf + * + * @return input parameter for testValueOf + */ + @DataProvider + public Object[][] valueOfs() { + return new Object[][] { { String.valueOf(true), "true" }, + { String.valueOf(false), "false" }, + { String.valueOf(1.0f), "1.0" }, + { String.valueOf(0.0f), "0.0" }, + { String.valueOf(Float.MAX_VALUE), "3.4028235E38" }, + { String.valueOf(Float.MIN_VALUE), "1.4E-45" }, + { String.valueOf(1.0d), "1.0" }, + { String.valueOf(0.0d), "0.0" }, + { String.valueOf(Double.MAX_VALUE), "1.7976931348623157E308" }, + { String.valueOf(Double.MIN_VALUE), "4.9E-324" }, + { String.valueOf(1), "1" }, { String.valueOf(0), "0" }, + { String.valueOf(Integer.MAX_VALUE), "2147483647" }, + { String.valueOf(Integer.MIN_VALUE), "-2147483648" }, + { String.valueOf(1L), "1" }, { String.valueOf(0L), "0" }, + { String.valueOf(Long.MAX_VALUE), "9223372036854775807" }, + { String.valueOf(Long.MIN_VALUE), "-9223372036854775808" } }; + } + + /* + * test String.valueOf(xxx). + * + * @param res + * real result + * @param expected + * expected result + */ + @Test(dataProvider = "valueOfs") + public void testValueOf(String res, String expected) { + assertEquals(res, expected); + } + +} diff --git a/jdk/test/java/lang/String/LiteralReplace.java b/jdk/test/java/lang/String/LiteralReplace.java index f72e1050033427f58cdfa1d1c988d57d831fe834..32fc779408ffa9ce0561948aba1ae05b4b13a227 100644 --- a/jdk/test/java/lang/String/LiteralReplace.java +++ b/jdk/test/java/lang/String/LiteralReplace.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 8058779 + * @bug 8058779 8054307 * @library /lib/testlibrary/ * @build jdk.testlibrary.RandomFactory * @run testng LiteralReplace @@ -104,6 +104,109 @@ public class LiteralReplace { {"abcdefgh", "[a-h]", "X", "abcdefgh"}, {"aa+", "a+", "", "a"}, {"^abc$", "abc", "x", "^x$"}, + + // more with non-latin1 characters + {"\u4e00\u4e00\u4e00", + "\u4e00\u4e00", + "\u4e01", + "\u4e01\u4e00"}, + + {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08", + "\u4e03\u4e04\u4e05", + "\u4e10\u4e11\u4e12", + "\u4e00\u4e01\u4e02\u4e10\u4e11\u4e12\u4e06\u4e07\u4e08"}, + + {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08", + "ABC", + "\u4e10\u4e11\u4e12", + "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08"}, + + {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08", + "\u4e02\u4e03", + "\u4e12\u4e13", + "\u4e00\u4e01\u4e12\u4e13\u4e04\u4e12\u4e13\u4e07\u4e08"}, + + {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08", + "\u4e02\u4e03", + "ab", + "\u4e00\u4e01ab\u4e04ab\u4e07\u4e08"}, + + {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07", + "", + "_", + "_\u4e00_\u4e01_\u4e02_\u4e03_\u4e04_\u4e05_\u4e06_\u4e07_"}, + {"^\u4e00\u4e01\u4e02$", + "\u4e00\u4e01\u4e02", + "\u4e03", + "^\u4e03$"}, + + {"", "\u4e00", "\u4e01", ""}, + {"", "", "\u4e00\u4e01\u4e02", "\u4e00\u4e01\u4e02"}, + + {"^\u4e00\u4e01\u4e02$", + "\u4e00\u4e01\u4e02", + "X", + "^X$"}, + + {"abcdefgh", + "def", + "\u4e01", + "abc\u4e01gh"}, + + {"abcdefgh", + "def", + "\u4e01\u4e02", + "abc\u4e01\u4e02gh"}, + + {"abcdefabcgh", + "abc", + "\u4e01\u4e02", + "\u4e01\u4e02def\u4e01\u4e02gh"}, + + {"abcdefabcghabc", + "abc", + "\u4e01\u4e02", + "\u4e01\u4e02def\u4e01\u4e02gh\u4e01\u4e02"}, + + {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05", + "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05", + "abcd", + "abcd"}, + + {"\u4e00\u4e01", + "\u4e00\u4e01", + "abcdefg", + "abcdefg"}, + + {"\u4e00\u4e01xyz", + "\u4e00\u4e01", + "abcdefg", + "abcdefgxyz"}, + + {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00", + "\u4e00\u4e00", + "\u4e00\u4e00\u4e00", + "\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00"}, + + {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00", + "\u4e00\u4e00\u4e00", + "\u4e00\u4e00", + "\u4e00\u4e00\u4e00\u4e00"}, + + {"\u4e00.\u4e01.\u4e02.\u4e03.\u4e04.", + ".", + "-", + "\u4e00-\u4e01-\u4e02-\u4e03-\u4e04-"}, + + {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00", + "\u4e00", + "", + ""}, + + {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05", + "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05", + "", + ""}, }; } diff --git a/jdk/test/java/lang/String/ToLowerCase.java b/jdk/test/java/lang/String/ToLowerCase.java index 784f810e052acd081355d066dfee076a208d4181..9b5574d6f961ac76456f50101d9c01a6e4e454cc 100644 --- a/jdk/test/java/lang/String/ToLowerCase.java +++ b/jdk/test/java/lang/String/ToLowerCase.java @@ -23,7 +23,7 @@ /* @test - @bug 4217441 4533872 4900935 8020037 8032012 8041791 8042589 + @bug 4217441 4533872 4900935 8020037 8032012 8041791 8042589 8054307 @summary toLowerCase should lower-case Greek Sigma correctly depending on the context (final/non-final). Also it should handle Locale specific (lt, tr, and az) lowercasings and supplementary @@ -134,14 +134,60 @@ public class ToLowerCase { } test(src.toString(), Locale.US, exp.toString()); + // test latin1 + src = new StringBuilder(0x100); + exp = new StringBuilder(0x100); + for (int cp = 0; cp < 0x100; cp++) { + int lowerCase = Character.toLowerCase(cp); + if (lowerCase == -1) { //Character.ERROR + continue; + } + src.appendCodePoint(cp); + exp.appendCodePoint(lowerCase); + } + test(src.toString(), Locale.US, exp.toString()); + + // test non-latin1 -> latin1 + src = new StringBuilder(0x100).append("abc"); + exp = new StringBuilder(0x100).append("abc"); + for (int cp = 0x100; cp < 0x10000; cp++) { + int lowerCase = Character.toLowerCase(cp); + if (lowerCase < 0x100 && cp != '\u0130') { + src.appendCodePoint(cp); + exp.appendCodePoint(lowerCase); + } + } + test(src.toString(), Locale.US, exp.toString()); } static void test(String in, Locale locale, String expected) { + test0(in, locale,expected); + for (String[] ss : new String[][] { + new String[] {"abc", "abc"}, + new String[] {"aBc", "abc"}, + new String[] {"ABC", "abc"}, + new String[] {"ab\u4e00", "ab\u4e00"}, + new String[] {"aB\u4e00", "ab\u4e00"}, + new String[] {"AB\u4e00", "ab\u4e00"}, + new String[] {"ab\uD800\uDC00", "ab\uD800\uDC00"}, + new String[] {"aB\uD800\uDC00", "ab\uD800\uDC00"}, + new String[] {"AB\uD800\uDC00", "ab\uD800\uDC00"}, + new String[] {"ab\uD801\uDC1C", "ab\uD801\uDC44"}, + new String[] {"aB\uD801\uDC1C", "ab\uD801\uDC44"}, + new String[] {"AB\uD801\uDC1C", "ab\uD801\uDC44"}, + + }) { + test0(ss[0] + " " + in, locale, ss[1] + " " + expected); + test0(in + " " + ss[0], locale, expected + " " + ss[1]); + } + } + + static void test0(String in, Locale locale, String expected) { String result = in.toLowerCase(locale); if (!result.equals(expected)) { System.err.println("input: " + in + ", locale: " + locale + ", expected: " + expected + ", actual: " + result); throw new RuntimeException(); } - } + } } diff --git a/jdk/test/java/lang/String/ToUpperCase.java b/jdk/test/java/lang/String/ToUpperCase.java index 020c2ae02da5a5ab6038457e8e7a75ab9052a366..b7cebc1a3024e47d9ccb65cfe5808dea2a69c642 100644 --- a/jdk/test/java/lang/String/ToUpperCase.java +++ b/jdk/test/java/lang/String/ToUpperCase.java @@ -23,7 +23,7 @@ /* @test - @bug 4219630 4304573 4533872 4900935 8042589 + @bug 4219630 4304573 4533872 4900935 8042589 8054307 @summary toUpperCase should upper-case German sharp s correctly even if it's the only character in the string. should also uppercase all of the 1:M char mappings correctly. Also it should handle @@ -97,14 +97,66 @@ public class ToUpperCase { test("A\uD801\uDC44", Locale.ROOT, "A\uD801\uDC1c"); test("a\uD801\uDC28\uD801\uDC29\uD801\uDC2A", Locale.US, "A\uD801\uDC00\uD801\uDC01\uD801\uDC02"); test("A\uD801\uDC28a\uD801\uDC29b\uD801\uDC2Ac", Locale.US, "A\uD801\uDC00A\uD801\uDC01B\uD801\uDC02C"); + + // test latin1 only case + StringBuilder src = new StringBuilder(0x100); + StringBuilder exp = new StringBuilder(0x100); + for (int cp = 0; cp < 0x100; cp++) { + int upperCase = Character.toUpperCase(cp); + if (upperCase == -1) { //Character.ERROR + continue; + } + src.appendCodePoint(cp); + if (cp == '\u00df') { + exp.append("SS"); // need Character.toUpperCaseEx() + } else { + exp.appendCodePoint(upperCase); + } + } + test(src.toString(), Locale.US, exp.toString()); + + // test non-latin1 -> latin1 + src = new StringBuilder(0x100).append("ABC"); + exp = new StringBuilder(0x100).append("ABC"); + for (int cp = 0x100; cp < 0x10000; cp++) { + int upperCase = Character.toUpperCase(cp); + if (upperCase < 0x100) { + src.appendCodePoint(cp); + exp.appendCodePoint(upperCase); + } + } + test(src.toString(), Locale.US, exp.toString()); + } static void test(String in, Locale locale, String expected) { + test0(in, locale,expected); + // trigger different code paths + for (String[] ss : new String[][] { + new String[] {"abc", "ABC"}, + new String[] {"AbC", "ABC"}, + new String[] {"ABC", "ABC"}, + new String[] {"AB\u4e00", "AB\u4e00"}, + new String[] {"ab\u4e00", "AB\u4e00"}, + new String[] {"aB\u4e00", "AB\u4e00"}, + new String[] {"AB\uD800\uDC00", "AB\uD800\uDC00"}, + new String[] {"Ab\uD800\uDC00", "AB\uD800\uDC00"}, + new String[] {"ab\uD800\uDC00", "AB\uD800\uDC00"}, + new String[] {"AB\uD801\uDC44", "AB\uD801\uDC1C"}, + new String[] {"Ab\uD801\uDC44", "AB\uD801\uDC1C"}, + new String[] {"ab\uD801\uDC44", "AB\uD801\uDC1C"}, + }) { + test0(ss[0] + " " + in, locale, ss[1] + " " + expected); + test0(in + " " + ss[0], locale, expected + " " + ss[1]); + } + } + + static void test0(String in, Locale locale, String expected) { String result = in.toUpperCase(locale); if (!result.equals(expected)) { System.err.println("input: " + in + ", locale: " + locale + ", expected: " + expected + ", actual: " + result); throw new RuntimeException(); } - } + } } diff --git a/jdk/test/java/lang/StringBuffer/CompactStringBuffer.java b/jdk/test/java/lang/StringBuffer/CompactStringBuffer.java new file mode 100644 index 0000000000000000000000000000000000000000..bc0ec5f6d08c19334ee173a87051b330f32ce0da --- /dev/null +++ b/jdk/test/java/lang/StringBuffer/CompactStringBuffer.java @@ -0,0 +1,489 @@ +/* + * 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.util.Arrays; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String. This test is testing StringBuffer + * behavior related to Compact String. + * @run testng/othervm -XX:+CompactStrings CompactStringBuffer + * @run testng/othervm -XX:-CompactStrings CompactStringBuffer + */ + +public class CompactStringBuffer { + + /* + * Tests for "A" + */ + @Test + public void testCompactStringBufferForLatinA() { + final String ORIGIN = "A"; + /* + * Because right now ASCII is the default encoding parameter for source + * code in JDK build environment, so we escape them. same as below. + */ + check(new StringBuffer(ORIGIN).append(new char[] { '\uFF21' }), + "A\uFF21"); + check(new StringBuffer(ORIGIN).append(new StringBuffer("\uFF21")), + "A\uFF21"); + check(new StringBuffer(ORIGIN).append("\uFF21"), "A\uFF21"); + check(new StringBuffer(ORIGIN).append(new StringBuffer("\uFF21")), + "A\uFF21"); + check(new StringBuffer(ORIGIN).delete(0, 1), ""); + check(new StringBuffer(ORIGIN).delete(0, 0), "A"); + check(new StringBuffer(ORIGIN).deleteCharAt(0), ""); + assertEquals(new StringBuffer(ORIGIN).indexOf("A", 0), 0); + assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 0), -1); + assertEquals(new StringBuffer(ORIGIN).indexOf("", 0), 0); + assertEquals(new StringBuffer(ORIGIN).insert(1, "\uD801\uDC00") + .indexOf("A", 0), 0); + assertEquals(new StringBuffer(ORIGIN).insert(0, "\uD801\uDC00") + .indexOf("A", 0), 2); + check(new StringBuffer(ORIGIN).insert(0, new char[] {}), "A"); + check(new StringBuffer(ORIGIN).insert(1, new char[] { '\uFF21' }), + "A\uFF21"); + check(new StringBuffer(ORIGIN).insert(0, new char[] { '\uFF21' }), + "\uFF21A"); + check(new StringBuffer(ORIGIN).insert(0, new StringBuffer("\uFF21")), + "\uFF21A"); + check(new StringBuffer(ORIGIN).insert(1, new StringBuffer("\uFF21")), + "A\uFF21"); + check(new StringBuffer(ORIGIN).insert(0, ""), "A"); + check(new StringBuffer(ORIGIN).insert(0, "\uFF21"), "\uFF21A"); + check(new StringBuffer(ORIGIN).insert(1, "\uFF21"), "A\uFF21"); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 0); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), -1); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 1); + check(new StringBuffer(ORIGIN).replace(0, 0, "\uFF21"), "\uFF21A"); + check(new StringBuffer(ORIGIN).replace(0, 1, "\uFF21"), "\uFF21"); + checkSetCharAt(new StringBuffer(ORIGIN), 0, '\uFF21', "\uFF21"); + checkSetLength(new StringBuffer(ORIGIN), 0, ""); + checkSetLength(new StringBuffer(ORIGIN), 1, "A"); + check(new StringBuffer(ORIGIN).substring(0), "A"); + check(new StringBuffer(ORIGIN).substring(1), ""); + } + + /* + * Tests for "\uFF21" + */ + @Test + public void testCompactStringBufferForNonLatinA() { + final String ORIGIN = "\uFF21"; + check(new StringBuffer(ORIGIN).append(new char[] { 'A' }), "\uFF21A"); + check(new StringBuffer(ORIGIN).append(new StringBuffer("A")), "\uFF21A"); + check(new StringBuffer(ORIGIN).append("A"), "\uFF21A"); + check(new StringBuffer(ORIGIN).append(new StringBuffer("A")), "\uFF21A"); + check(new StringBuffer(ORIGIN).delete(0, 1), ""); + check(new StringBuffer(ORIGIN).delete(0, 0), "\uFF21"); + check(new StringBuffer(ORIGIN).deleteCharAt(0), ""); + assertEquals(new StringBuffer(ORIGIN).indexOf("A", 0), -1); + assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 0), 0); + assertEquals(new StringBuffer(ORIGIN).indexOf("", 0), 0); + check(new StringBuffer(ORIGIN).insert(0, new char[] {}), "\uFF21"); + check(new StringBuffer(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21A"); + check(new StringBuffer(ORIGIN).insert(0, new char[] { 'A' }), "A\uFF21"); + check(new StringBuffer(ORIGIN).insert(0, new StringBuffer("A")), + "A\uFF21"); + check(new StringBuffer(ORIGIN).insert(1, new StringBuffer("A")), + "\uFF21A"); + check(new StringBuffer(ORIGIN).insert(0, ""), "\uFF21"); + check(new StringBuffer(ORIGIN).insert(0, "A"), "A\uFF21"); + check(new StringBuffer(ORIGIN).insert(1, "A"), "\uFF21A"); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), -1); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 0); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 1); + check(new StringBuffer(ORIGIN).replace(0, 0, "A"), "A\uFF21"); + check(new StringBuffer(ORIGIN).replace(0, 1, "A"), "A"); + checkSetCharAt(new StringBuffer(ORIGIN), 0, 'A', "A"); + checkSetLength(new StringBuffer(ORIGIN), 0, ""); + checkSetLength(new StringBuffer(ORIGIN), 1, "\uFF21"); + check(new StringBuffer(ORIGIN).substring(0), "\uFF21"); + check(new StringBuffer(ORIGIN).substring(1), ""); + } + + /* + * Tests for "\uFF21A" + */ + @Test + public void testCompactStringBufferForMixedA1() { + final String ORIGIN = "\uFF21A"; + check(new StringBuffer(ORIGIN).delete(0, 1), "A"); + check(new StringBuffer(ORIGIN).delete(1, 2), "\uFF21"); + check(new StringBuffer(ORIGIN).deleteCharAt(1), "\uFF21"); + check(new StringBuffer(ORIGIN).deleteCharAt(0), "A"); + assertEquals(new StringBuffer(ORIGIN).indexOf("A", 0), 1); + assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 0), 0); + assertEquals(new StringBuffer(ORIGIN).indexOf("", 0), 0); + check(new StringBuffer(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21AA"); + check(new StringBuffer(ORIGIN).insert(0, new char[] { '\uFF21' }), + "\uFF21\uFF21A"); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 1); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 0); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 2); + check(new StringBuffer(ORIGIN).replace(0, 0, "A"), "A\uFF21A"); + check(new StringBuffer(ORIGIN).replace(0, 1, "A"), "AA"); + checkSetCharAt(new StringBuffer(ORIGIN), 0, 'A', "AA"); + checkSetLength(new StringBuffer(ORIGIN), 0, ""); + checkSetLength(new StringBuffer(ORIGIN), 1, "\uFF21"); + check(new StringBuffer(ORIGIN).substring(0), "\uFF21A"); + check(new StringBuffer(ORIGIN).substring(1), "A"); + } + + /* + * Tests for "A\uFF21" + */ + @Test + public void testCompactStringBufferForMixedA2() { + final String ORIGIN = "A\uFF21"; + check(new StringBuffer(ORIGIN).replace(1, 2, "A"), "AA"); + checkSetLength(new StringBuffer(ORIGIN), 1, "A"); + check(new StringBuffer(ORIGIN).substring(0), "A\uFF21"); + check(new StringBuffer(ORIGIN).substring(1), "\uFF21"); + check(new StringBuffer(ORIGIN).substring(0, 1), "A"); + } + + /* + * Tests for "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" + */ + @Test + public void testCompactStringBufferForDuplicatedMixedA1() { + final String ORIGIN = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A"; + checkSetLength(new StringBuffer(ORIGIN), 1, "\uFF21"); + assertEquals(new StringBuffer(ORIGIN).indexOf("A", 5), 5); + assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 5), 6); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 9); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 8); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 10); + check(new StringBuffer(ORIGIN).substring(9), "A"); + check(new StringBuffer(ORIGIN).substring(8), "\uFF21A"); + } + + /* + * Tests for "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21" + */ + @Test + public void testCompactStringBufferForDuplicatedMixedA2() { + final String ORIGIN = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21"; + checkSetLength(new StringBuffer(ORIGIN), 1, "A"); + assertEquals(new StringBuffer(ORIGIN).indexOf("A", 5), 6); + assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 5), 5); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 8); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 9); + check(new StringBuffer(ORIGIN).substring(9), "\uFF21"); + check(new StringBuffer(ORIGIN).substring(8), "A\uFF21"); + } + + /* + * Tests for "\uD801\uDC00\uD801\uDC01" + */ + @Test + public void testCompactStringForSupplementaryCodePoint() { + final String ORIGIN = "\uD801\uDC00\uD801\uDC01"; + check(new StringBuffer(ORIGIN).append("A"), "\uD801\uDC00\uD801\uDC01A"); + check(new StringBuffer(ORIGIN).append("\uFF21"), + "\uD801\uDC00\uD801\uDC01\uFF21"); + check(new StringBuffer(ORIGIN).appendCodePoint('A'), + "\uD801\uDC00\uD801\uDC01A"); + check(new StringBuffer(ORIGIN).appendCodePoint('\uFF21'), + "\uD801\uDC00\uD801\uDC01\uFF21"); + assertEquals(new StringBuffer(ORIGIN).charAt(0), '\uD801'); + assertEquals(new StringBuffer(ORIGIN).codePointAt(0), + Character.codePointAt(ORIGIN, 0)); + assertEquals(new StringBuffer(ORIGIN).codePointAt(1), + Character.codePointAt(ORIGIN, 1)); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), + Character.codePointAt(ORIGIN, 0)); + assertEquals(new StringBuffer(ORIGIN).codePointCount(1, 3), 2); + check(new StringBuffer(ORIGIN).delete(0, 2), "\uD801\uDC01"); + check(new StringBuffer(ORIGIN).delete(0, 3), "\uDC01"); + check(new StringBuffer(ORIGIN).deleteCharAt(1), "\uD801\uD801\uDC01"); + checkGetChars(new StringBuffer(ORIGIN), 0, 3, new char[] { '\uD801', + '\uDC00', '\uD801' }); + assertEquals(new StringBuffer(ORIGIN).indexOf("\uD801\uDC01"), 2); + assertEquals(new StringBuffer(ORIGIN).indexOf("\uDC01"), 3); + assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21"), -1); + assertEquals(new StringBuffer(ORIGIN).indexOf("A"), -1); + check(new StringBuffer(ORIGIN).insert(0, "\uFF21"), + "\uFF21\uD801\uDC00\uD801\uDC01"); + check(new StringBuffer(ORIGIN).insert(1, "\uFF21"), + "\uD801\uFF21\uDC00\uD801\uDC01"); + check(new StringBuffer(ORIGIN).insert(1, "A"), + "\uD801A\uDC00\uD801\uDC01"); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uDC00\uD801"), 1); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uD801"), 2); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), -1); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), -1); + assertEquals(new StringBuffer(ORIGIN).length(), 4); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 2); + check(new StringBuffer(ORIGIN).replace(0, 2, "A"), "A\uD801\uDC01"); + check(new StringBuffer(ORIGIN).replace(0, 3, "A"), "A\uDC01"); + check(new StringBuffer(ORIGIN).replace(0, 2, "\uFF21"), + "\uFF21\uD801\uDC01"); + check(new StringBuffer(ORIGIN).replace(0, 3, "\uFF21"), "\uFF21\uDC01"); + check(new StringBuffer(ORIGIN).reverse(), "\uD801\uDC01\uD801\uDC00"); + checkSetCharAt(new StringBuffer(ORIGIN), 1, '\uDC01', + "\uD801\uDC01\uD801\uDC01"); + checkSetCharAt(new StringBuffer(ORIGIN), 1, 'A', "\uD801A\uD801\uDC01"); + checkSetLength(new StringBuffer(ORIGIN), 2, "\uD801\uDC00"); + checkSetLength(new StringBuffer(ORIGIN), 3, "\uD801\uDC00\uD801"); + check(new StringBuffer(ORIGIN).substring(1, 3), "\uDC00\uD801"); + } + + /* + * Tests for "A\uD801\uDC00\uFF21" + */ + @Test + public void testCompactStringForSupplementaryCodePointMixed1() { + final String ORIGIN = "A\uD801\uDC00\uFF21"; + assertEquals(new StringBuffer(ORIGIN).codePointBefore(3), + Character.codePointAt(ORIGIN, 1)); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), '\uD801'); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), 'A'); + assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 2); + assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 4), 3); + check(new StringBuffer(ORIGIN).delete(0, 1), "\uD801\uDC00\uFF21"); + check(new StringBuffer(ORIGIN).delete(0, 1).delete(2, 3), "\uD801\uDC00"); + check(new StringBuffer(ORIGIN).deleteCharAt(3).deleteCharAt(0), + "\uD801\uDC00"); + assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21"), 3); + assertEquals(new StringBuffer(ORIGIN).indexOf("A"), 0); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 3); + assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 0); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 1); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 3); + check(new StringBuffer(ORIGIN).replace(1, 3, "A"), "AA\uFF21"); + check(new StringBuffer(ORIGIN).replace(1, 4, "A"), "AA"); + check(new StringBuffer(ORIGIN).replace(1, 4, ""), "A"); + check(new StringBuffer(ORIGIN).reverse(), "\uFF21\uD801\uDC00A"); + checkSetLength(new StringBuffer(ORIGIN), 1, "A"); + check(new StringBuffer(ORIGIN).substring(0, 1), "A"); + } + + /* + * Tests for "\uD801\uDC00\uFF21A" + */ + @Test + public void testCompactStringForSupplementaryCodePointMixed2() { + final String ORIGIN = "\uD801\uDC00\uFF21A"; + assertEquals(new StringBuffer(ORIGIN).codePointBefore(3), + Character.codePointAt(ORIGIN, 2)); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), + Character.codePointAt(ORIGIN, 0)); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), '\uD801'); + assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 2); + assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 4), 3); + check(new StringBuffer(ORIGIN).delete(0, 2), "\uFF21A"); + check(new StringBuffer(ORIGIN).delete(0, 3), "A"); + check(new StringBuffer(ORIGIN).deleteCharAt(0).deleteCharAt(0) + .deleteCharAt(0), "A"); + assertEquals(new StringBuffer(ORIGIN).indexOf("A"), 3); + assertEquals(new StringBuffer(ORIGIN).delete(0, 3).indexOf("A"), 0); + assertEquals(new StringBuffer(ORIGIN).replace(0, 3, "B").indexOf("A"), + 1); + assertEquals(new StringBuffer(ORIGIN).substring(3, 4).indexOf("A"), 0); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 2); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(2, 1), 3); + check(new StringBuffer(ORIGIN).replace(0, 3, "B"), "BA"); + check(new StringBuffer(ORIGIN).reverse(), "A\uFF21\uD801\uDC00"); + } + + /* + * Tests for "\uD801A\uDC00\uFF21" + */ + @Test + public void testCompactStringForSupplementaryCodePointMixed3() { + final String ORIGIN = "\uD801A\uDC00\uFF21"; + assertEquals(new StringBuffer(ORIGIN).codePointAt(1), 'A'); + assertEquals(new StringBuffer(ORIGIN).codePointAt(3), '\uFF21'); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), '\uD801'); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), 'A'); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(3), '\uDC00'); + assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 3); + assertEquals(new StringBuffer(ORIGIN).codePointCount(1, 3), 2); + assertEquals(new StringBuffer(ORIGIN).delete(0, 1).delete(1, 3) + .indexOf("A"), 0); + assertEquals( + new StringBuffer(ORIGIN).replace(0, 1, "B").replace(2, 4, "C") + .indexOf("A"), 1); + assertEquals(new StringBuffer(ORIGIN).substring(1, 4).substring(0, 1) + .indexOf("A"), 0); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 1); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(2, 1), 3); + check(new StringBuffer(ORIGIN).reverse(), "\uFF21\uDC00A\uD801"); + } + + /* + * Tests for "A\uDC01\uFF21\uD801" + */ + @Test + public void testCompactStringForSupplementaryCodePointMixed4() { + final String ORIGIN = "A\uDC01\uFF21\uD801"; + assertEquals(new StringBuffer(ORIGIN).codePointAt(1), '\uDC01'); + assertEquals(new StringBuffer(ORIGIN).codePointAt(3), '\uD801'); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), 'A'); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), '\uDC01'); + assertEquals(new StringBuffer(ORIGIN).codePointBefore(3), '\uFF21'); + assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 3); + assertEquals(new StringBuffer(ORIGIN).codePointCount(1, 3), 2); + assertEquals(new StringBuffer(ORIGIN).delete(1, 4).indexOf("A"), 0); + assertEquals(new StringBuffer(ORIGIN).replace(1, 4, "B").indexOf("A"), + 0); + assertEquals(new StringBuffer(ORIGIN).substring(0, 1).indexOf("A"), 0); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 1); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2); + assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(2, 1), 3); + check(new StringBuffer(ORIGIN).reverse(), "\uD801\uFF21\uDC01A"); + } + + @Test + public void testCompactStringMisc() { + String ascii = "abcdefgh"; + String asciiMixed = "abc" + "\u4e00\u4e01\u4e02" + "fgh"; + String bmp = "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08"; + String bmpMixed = "\u4e00\u4e01\u4e02" + "ABC" + "\u4e06\u4e07\u4e08"; + + check(new StringBuffer().append(ascii).delete(0, 20).toString(), + ""); + check(new StringBuffer().append(ascii).delete(3, 20).toString(), + "abc"); + check(new StringBuffer().append(ascii).delete(3, 6).toString(), + "abcgh"); + check(new StringBuffer().append(ascii).deleteCharAt(0).toString(), + "bcdefgh"); + check(new StringBuffer().append(ascii).deleteCharAt(3).toString(), + "abcefgh"); + check(new StringBuffer().append(asciiMixed).delete(3, 6).toString(), + "abcfgh"); + check(new StringBuffer().append(asciiMixed).deleteCharAt(3).toString(), + "abc\u4e01\u4e02fgh"); + check(new StringBuffer().append(asciiMixed).deleteCharAt(3) + .deleteCharAt(3) + .deleteCharAt(3).toString(), + "abcfgh"); + check(new StringBuffer().append(bmp).delete(0, 20).toString(), + ""); + check(new StringBuffer().append(bmp).delete(3, 20).toString(), + "\u4e00\u4e01\u4e02"); + check(new StringBuffer().append(bmp).delete(3, 6).toString(), + "\u4e00\u4e01\u4e02\u4e06\u4e07\u4e08"); + check(new StringBuffer().append(bmp).deleteCharAt(0).toString(), + "\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08"); + check(new StringBuffer().append(bmp).deleteCharAt(3).toString(), + "\u4e00\u4e01\u4e02\u4e04\u4e05\u4e06\u4e07\u4e08"); + check(new StringBuffer().append(bmpMixed).delete(3, 6).toString(), + "\u4e00\u4e01\u4e02\u4e06\u4e07\u4e08"); + + //////////////////////////////////////////////////////////////////// + check(new StringBuffer().append(ascii).replace(3, 6, "AB").toString(), + "abcABgh"); + check(new StringBuffer().append(asciiMixed).replace(3, 6, "AB").toString(), + "abcABfgh"); + check(new StringBuffer().append(bmp).replace(3, 6, "AB").toString(), + "\u4e00\u4e01\u4e02AB\u4e06\u4e07\u4e08"); + + check(new StringBuffer().append(bmpMixed).replace(3, 6, "").toString(), + "\u4e00\u4e01\u4e02\u4e06\u4e07\u4e08"); + + check(new StringBuffer().append(ascii).replace(3, 6, "\u4e01\u4e02").toString(), + "abc\u4e01\u4e02gh"); + + //////////////////////////////////////////////////////////////////// + check(new StringBuffer().append(ascii).insert(3, "").toString(), + "abcdefgh"); + check(new StringBuffer().append(ascii).insert(3, "AB").toString(), + "abcABdefgh"); + check(new StringBuffer().append(ascii).insert(3, "\u4e01\u4e02").toString(), + "abc\u4e01\u4e02defgh"); + + check(new StringBuffer().append(asciiMixed).insert(0, 'A').toString(), + "Aabc\u4e00\u4e01\u4e02fgh"); + check(new StringBuffer().append(asciiMixed).insert(3, "A").toString(), + "abcA\u4e00\u4e01\u4e02fgh"); + + check(new StringBuffer().append(ascii).insert(3, 1234567).toString(), + "abc1234567defgh"); + check(new StringBuffer().append(bmp).insert(3, 1234567).toString(), + "\u4e00\u4e01\u4e021234567\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08"); + + //////////////////////////////////////////////////////////////////// + check(new StringBuffer().append(ascii).append(1.23456).toString(), + "abcdefgh1.23456"); + check(new StringBuffer().append(bmp).append(1.23456).toString(), + "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e081.23456"); + } + + private void checkGetChars(StringBuffer sb, int srcBegin, int srcEnd, + char expected[]) { + char[] dst = new char[srcEnd - srcBegin]; + sb.getChars(srcBegin, srcEnd, dst, 0); + assertTrue(Arrays.equals(dst, expected)); + } + + private void checkSetCharAt(StringBuffer sb, int index, char ch, + String expected) { + sb.setCharAt(index, ch); + check(sb, expected); + } + + private void checkSetLength(StringBuffer sb, int newLength, String expected) { + sb.setLength(newLength); + check(sb, expected); + } + + private void check(StringBuffer sb, String expected) { + check(sb.toString(), expected); + } + + private void check(String str, String expected) { + assertTrue(str.equals(expected), String.format( + "Get (%s) but expect (%s), ", escapeNonASCIIs(str), + escapeNonASCIIs(expected))); + } + + /* + * Because right now system default charset in JPRT environment is only + * guaranteed to support ASCII characters in log, so we escape them. + */ + private String escapeNonASCIIs(String str) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c > 0x7F) { + sb.append("\\u").append(Integer.toHexString((int) c)); + } else { + sb.append(c); + } + } + return sb.toString(); + } +} diff --git a/jdk/test/java/lang/StringBuffer/CompactStringBufferSerialization.java b/jdk/test/java/lang/StringBuffer/CompactStringBufferSerialization.java new file mode 100644 index 0000000000000000000000000000000000000000..346c824ed1208ca978b79e080005ce13e814f2eb --- /dev/null +++ b/jdk/test/java/lang/StringBuffer/CompactStringBufferSerialization.java @@ -0,0 +1,152 @@ +/* + * 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.io.*; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static jdk.testlibrary.SerializationUtils.*; +import static org.testng.Assert.*; + +/* + * @test + * @bug 8077559 + * @library /lib/testlibrary + * @build jdk.testlibrary.SerializationUtils + * @summary Tests Compact String. This one is testing StringBuffer serialization + * among -XX:+CompactStrings/-XX:-CompactStrings/LegacyStringBuffer + * @run testng/othervm -XX:+CompactStrings CompactStringBufferSerialization + * @run testng/othervm -XX:-CompactStrings CompactStringBufferSerialization + */ + +public class CompactStringBufferSerialization { + @DataProvider + public Object[][] provider() { + return new Object[][] { + // every byte array is serialized from corresponding StringBuilder object + // by previous JDK(build 1.8.0_45-b14). + new Object[] { + new StringBuffer(""), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 0, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("A"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 1, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("AB"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 2, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, 0, 65, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("abcdefghijk"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 11, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 27, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0, 105, 0, + 106, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("\uff21"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 1, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, -1, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("\uff21\uff22"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 2, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, -1, 33, -1, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("\uff21A\uff21A\uff21A\uff21A\uff21A"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 10, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("A\uff21B\uff22C\uff23D\uff24E\uff25F\uff26G\uff27H\uff28"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 16, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, 0, 65, -1, 33, 0, 66, -1, 34, 0, 67, -1, 35, 0, 68, -1, 36, 0, 69, -1, 37, + 0, 70, -1, 38, 0, 71, -1, 39, 0, 72, -1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("\uff21A\uff22B\uff23C\uff24D\uff25E\uff26F\uff27G\uff28H"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 16, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, -1, 33, 0, 65, -1, 34, 0, 66, -1, 35, 0, 67, -1, 36, 0, 68, -1, 37, 0, 69, + -1, 38, 0, 70, -1, 39, 0, 71, -1, 40, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("\ud801\udc00\ud801\udc01\uff21A"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 6, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 22, -40, 1, -36, 0, -40, 1, -36, 1, -1, 33, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuffer("\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102, + 102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101, + 100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 10, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80, + -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, + 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } } }; + } + + /* + * Verify serialization works between Compact StringBuffer/Legacy StringBuffer + */ + @Test(dataProvider = "provider") + public void test(StringBuffer sbContent, byte[] baInJDK8) throws Exception { + // Serialize a StringBuffer object into byte array. + byte[] ba = serialize(sbContent); + assertEquals(ba, baInJDK8); + // Deserialize a StringBuffer object from byte array which is generated by previous JDK(build 1.8.0_45-b14). + Object obj = deserialize(ba); + assertEquals(obj.getClass(), StringBuffer.class); + assertTrue(equals((StringBuffer)obj, sbContent)); + } + + boolean equals(StringBuffer sb, StringBuffer expected) { + if(sb.length() == expected.length() + && sb.capacity() == expected.capacity() + && sb.toString().equals(expected.toString())) { + return true; + } + return false; + } +} diff --git a/jdk/test/java/lang/StringBuffer/Exceptions.java b/jdk/test/java/lang/StringBuffer/Exceptions.java index 5f68b800b56bb41dbffad118b2a2e6874d524c75..061b3d75d7c9cf87d741c1fbbc64c4e30ae2fc58 100644 --- a/jdk/test/java/lang/StringBuffer/Exceptions.java +++ b/jdk/test/java/lang/StringBuffer/Exceptions.java @@ -94,7 +94,7 @@ public class Exceptions { System.out.println("StringBuffer.replace(int start, int end, String str)"); tryCatch(" -1, 2, \" \"", - new StringIndexOutOfBoundsException(-1), + new StringIndexOutOfBoundsException("start -1, end 2, length 7"), new Runnable() { public void run() { StringBuffer sb = new StringBuffer("hilbert"); @@ -102,14 +102,14 @@ public class Exceptions { }}); tryCatch(" 7, 8, \" \"", - new StringIndexOutOfBoundsException("start > length()"), + new StringIndexOutOfBoundsException("start 7, end 6, length 6"), new Runnable() { public void run() { StringBuffer sb = new StringBuffer("banach"); sb.replace(7, 8, " "); }}); tryCatch(" 2, 1, \" \"", - new StringIndexOutOfBoundsException("start > end"), + new StringIndexOutOfBoundsException("start 2, end 1, length 7"), new Runnable() { public void run() { StringBuffer sb = new StringBuffer("riemann"); diff --git a/jdk/test/java/lang/StringBuilder/BuilderForwarding.java b/jdk/test/java/lang/StringBuilder/BuilderForwarding.java index a78c3232b1759210cf02fe85d98156ffdef40090..82e40108d4cc6dc6d44c40ac3bbc3a69bbd9131e 100644 --- a/jdk/test/java/lang/StringBuilder/BuilderForwarding.java +++ b/jdk/test/java/lang/StringBuilder/BuilderForwarding.java @@ -264,4 +264,3 @@ public class BuilderForwarding { } } } - diff --git a/jdk/test/java/lang/StringBuilder/CompactStringBuilder.java b/jdk/test/java/lang/StringBuilder/CompactStringBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..7c69326aca8dead21e5a71866700752012d6710f --- /dev/null +++ b/jdk/test/java/lang/StringBuilder/CompactStringBuilder.java @@ -0,0 +1,414 @@ +/* + * 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.util.Arrays; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/* + * @test + * @bug 8054307 8077559 + * @summary Tests Compact String. This test is testing StringBuilder + * behavior related to Compact String. + * @run testng/othervm -XX:+CompactStrings CompactStringBuilder + * @run testng/othervm -XX:-CompactStrings CompactStringBuilder + */ + +public class CompactStringBuilder { + + /* + * Tests for "A" + */ + @Test + public void testCompactStringBuilderForLatinA() { + final String ORIGIN = "A"; + /* + * Because right now ASCII is the default encoding parameter for source + * code in JDK build environment, so we escape them. same as below. + */ + check(new StringBuilder(ORIGIN).append(new char[] { '\uFF21' }), + "A\uFF21"); + check(new StringBuilder(ORIGIN).append(new StringBuffer("\uFF21")), + "A\uFF21"); + check(new StringBuilder(ORIGIN).append("\uFF21"), "A\uFF21"); + check(new StringBuilder(ORIGIN).append(new StringBuffer("\uFF21")), + "A\uFF21"); + check(new StringBuilder(ORIGIN).delete(0, 1), ""); + check(new StringBuilder(ORIGIN).delete(0, 0), "A"); + check(new StringBuilder(ORIGIN).deleteCharAt(0), ""); + assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), 0); + assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), -1); + assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0); + assertEquals(new StringBuilder(ORIGIN).insert(1, "\uD801\uDC00") + .indexOf("A", 0), 0); + assertEquals(new StringBuilder(ORIGIN).insert(0, "\uD801\uDC00") + .indexOf("A", 0), 2); + check(new StringBuilder(ORIGIN).insert(0, new char[] {}), "A"); + check(new StringBuilder(ORIGIN).insert(1, new char[] { '\uFF21' }), + "A\uFF21"); + check(new StringBuilder(ORIGIN).insert(0, new char[] { '\uFF21' }), + "\uFF21A"); + check(new StringBuilder(ORIGIN).insert(0, new StringBuffer("\uFF21")), + "\uFF21A"); + check(new StringBuilder(ORIGIN).insert(1, new StringBuffer("\uFF21")), + "A\uFF21"); + check(new StringBuilder(ORIGIN).insert(0, ""), "A"); + check(new StringBuilder(ORIGIN).insert(0, "\uFF21"), "\uFF21A"); + check(new StringBuilder(ORIGIN).insert(1, "\uFF21"), "A\uFF21"); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 0); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), -1); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 1); + check(new StringBuilder(ORIGIN).replace(0, 0, "\uFF21"), "\uFF21A"); + check(new StringBuilder(ORIGIN).replace(0, 1, "\uFF21"), "\uFF21"); + checkSetCharAt(new StringBuilder(ORIGIN), 0, '\uFF21', "\uFF21"); + checkSetLength(new StringBuilder(ORIGIN), 0, ""); + checkSetLength(new StringBuilder(ORIGIN), 1, "A"); + check(new StringBuilder(ORIGIN).substring(0), "A"); + check(new StringBuilder(ORIGIN).substring(1), ""); + } + + /* + * Tests for "\uFF21" + */ + @Test + public void testCompactStringBuilderForNonLatinA() { + final String ORIGIN = "\uFF21"; + check(new StringBuilder(ORIGIN).append(new char[] { 'A' }), "\uFF21A"); + check(new StringBuilder(ORIGIN).append(new StringBuffer("A")), "\uFF21A"); + check(new StringBuilder(ORIGIN).append("A"), "\uFF21A"); + check(new StringBuilder(ORIGIN).append(new StringBuffer("A")), "\uFF21A"); + check(new StringBuilder(ORIGIN).delete(0, 1), ""); + check(new StringBuilder(ORIGIN).delete(0, 0), "\uFF21"); + check(new StringBuilder(ORIGIN).deleteCharAt(0), ""); + assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), -1); + assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), 0); + assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0); + check(new StringBuilder(ORIGIN).insert(0, new char[] {}), "\uFF21"); + check(new StringBuilder(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21A"); + check(new StringBuilder(ORIGIN).insert(0, new char[] { 'A' }), "A\uFF21"); + check(new StringBuilder(ORIGIN).insert(0, new StringBuffer("A")), + "A\uFF21"); + check(new StringBuilder(ORIGIN).insert(1, new StringBuffer("A")), + "\uFF21A"); + check(new StringBuilder(ORIGIN).insert(0, ""), "\uFF21"); + check(new StringBuilder(ORIGIN).insert(0, "A"), "A\uFF21"); + check(new StringBuilder(ORIGIN).insert(1, "A"), "\uFF21A"); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), -1); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 0); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 1); + check(new StringBuilder(ORIGIN).replace(0, 0, "A"), "A\uFF21"); + check(new StringBuilder(ORIGIN).replace(0, 1, "A"), "A"); + checkSetCharAt(new StringBuilder(ORIGIN), 0, 'A', "A"); + checkSetLength(new StringBuilder(ORIGIN), 0, ""); + checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21"); + check(new StringBuilder(ORIGIN).substring(0), "\uFF21"); + check(new StringBuilder(ORIGIN).substring(1), ""); + } + + /* + * Tests for "\uFF21A" + */ + @Test + public void testCompactStringBuilderForMixedA1() { + final String ORIGIN = "\uFF21A"; + check(new StringBuilder(ORIGIN).delete(0, 1), "A"); + check(new StringBuilder(ORIGIN).delete(1, 2), "\uFF21"); + check(new StringBuilder(ORIGIN).deleteCharAt(1), "\uFF21"); + check(new StringBuilder(ORIGIN).deleteCharAt(0), "A"); + assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), 1); + assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), 0); + assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0); + check(new StringBuilder(ORIGIN).insert(1, new char[] { 'A' }), + "\uFF21AA"); + check(new StringBuilder(ORIGIN).insert(0, new char[] { '\uFF21' }), + "\uFF21\uFF21A"); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 1); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 0); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 2); + check(new StringBuilder(ORIGIN).replace(0, 0, "A"), "A\uFF21A"); + check(new StringBuilder(ORIGIN).replace(0, 1, "A"), "AA"); + checkSetCharAt(new StringBuilder(ORIGIN), 0, 'A', "AA"); + checkSetLength(new StringBuilder(ORIGIN), 0, ""); + checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21"); + check(new StringBuilder(ORIGIN).substring(0), "\uFF21A"); + check(new StringBuilder(ORIGIN).substring(1), "A"); + } + + /* + * Tests for "A\uFF21" + */ + @Test + public void testCompactStringBuilderForMixedA2() { + final String ORIGIN = "A\uFF21"; + check(new StringBuilder(ORIGIN).replace(1, 2, "A"), "AA"); + checkSetLength(new StringBuilder(ORIGIN), 1, "A"); + check(new StringBuilder(ORIGIN).substring(0), "A\uFF21"); + check(new StringBuilder(ORIGIN).substring(1), "\uFF21"); + check(new StringBuilder(ORIGIN).substring(0, 1), "A"); + } + + /* + * Tests for "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" + */ + @Test + public void testCompactStringBuilderForDuplicatedMixedA1() { + final String ORIGIN = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A"; + checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21"); + assertEquals(new StringBuilder(ORIGIN).indexOf("A", 5), 5); + assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 5), 6); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 9); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 8); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 10); + check(new StringBuilder(ORIGIN).substring(9), "A"); + check(new StringBuilder(ORIGIN).substring(8), "\uFF21A"); + } + + /* + * Tests for "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21" + */ + @Test + public void testCompactStringBuilderForDuplicatedMixedA2() { + final String ORIGIN = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21"; + checkSetLength(new StringBuilder(ORIGIN), 1, "A"); + assertEquals(new StringBuilder(ORIGIN).indexOf("A", 5), 6); + assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 5), 5); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 8); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 9); + check(new StringBuilder(ORIGIN).substring(9), "\uFF21"); + check(new StringBuilder(ORIGIN).substring(8), "A\uFF21"); + } + + /* + * Tests for "\uD801\uDC00\uD801\uDC01" + */ + @Test + public void testCompactStringForSupplementaryCodePoint() { + final String ORIGIN = "\uD801\uDC00\uD801\uDC01"; + check(new StringBuilder(ORIGIN).append("A"), "\uD801\uDC00\uD801\uDC01A"); + check(new StringBuilder(ORIGIN).append("\uFF21"), + "\uD801\uDC00\uD801\uDC01\uFF21"); + check(new StringBuilder(ORIGIN).appendCodePoint('A'), + "\uD801\uDC00\uD801\uDC01A"); + check(new StringBuilder(ORIGIN).appendCodePoint('\uFF21'), + "\uD801\uDC00\uD801\uDC01\uFF21"); + assertEquals(new StringBuilder(ORIGIN).charAt(0), '\uD801'); + assertEquals(new StringBuilder(ORIGIN).codePointAt(0), + Character.codePointAt(ORIGIN, 0)); + assertEquals(new StringBuilder(ORIGIN).codePointAt(1), + Character.codePointAt(ORIGIN, 1)); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), + Character.codePointAt(ORIGIN, 0)); + assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2); + check(new StringBuilder(ORIGIN).delete(0, 2), "\uD801\uDC01"); + check(new StringBuilder(ORIGIN).delete(0, 3), "\uDC01"); + check(new StringBuilder(ORIGIN).deleteCharAt(1), "\uD801\uD801\uDC01"); + checkGetChars(new StringBuilder(ORIGIN), 0, 3, new char[] { '\uD801', + '\uDC00', '\uD801' }); + assertEquals(new StringBuilder(ORIGIN).indexOf("\uD801\uDC01"), 2); + assertEquals(new StringBuilder(ORIGIN).indexOf("\uDC01"), 3); + assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21"), -1); + assertEquals(new StringBuilder(ORIGIN).indexOf("A"), -1); + check(new StringBuilder(ORIGIN).insert(0, "\uFF21"), + "\uFF21\uD801\uDC00\uD801\uDC01"); + check(new StringBuilder(ORIGIN).insert(1, "\uFF21"), + "\uD801\uFF21\uDC00\uD801\uDC01"); + check(new StringBuilder(ORIGIN).insert(1, "A"), + "\uD801A\uDC00\uD801\uDC01"); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uDC00\uD801"), 1); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uD801"), 2); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), -1); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), -1); + assertEquals(new StringBuilder(ORIGIN).length(), 4); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 2); + check(new StringBuilder(ORIGIN).replace(0, 2, "A"), "A\uD801\uDC01"); + check(new StringBuilder(ORIGIN).replace(0, 3, "A"), "A\uDC01"); + check(new StringBuilder(ORIGIN).replace(0, 2, "\uFF21"), + "\uFF21\uD801\uDC01"); + check(new StringBuilder(ORIGIN).replace(0, 3, "\uFF21"), "\uFF21\uDC01"); + check(new StringBuilder(ORIGIN).reverse(), "\uD801\uDC01\uD801\uDC00"); + checkSetCharAt(new StringBuilder(ORIGIN), 1, '\uDC01', + "\uD801\uDC01\uD801\uDC01"); + checkSetCharAt(new StringBuilder(ORIGIN), 1, 'A', "\uD801A\uD801\uDC01"); + checkSetLength(new StringBuilder(ORIGIN), 2, "\uD801\uDC00"); + checkSetLength(new StringBuilder(ORIGIN), 3, "\uD801\uDC00\uD801"); + check(new StringBuilder(ORIGIN).substring(1, 3), "\uDC00\uD801"); + } + + /* + * Tests for "A\uD801\uDC00\uFF21" + */ + @Test + public void testCompactStringForSupplementaryCodePointMixed1() { + final String ORIGIN = "A\uD801\uDC00\uFF21"; + assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), + Character.codePointAt(ORIGIN, 1)); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), '\uD801'); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), 'A'); + assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 2); + assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 4), 3); + check(new StringBuilder(ORIGIN).delete(0, 1), "\uD801\uDC00\uFF21"); + check(new StringBuilder(ORIGIN).delete(0, 1).delete(2, 3), + "\uD801\uDC00"); + check(new StringBuilder(ORIGIN).deleteCharAt(3).deleteCharAt(0), + "\uD801\uDC00"); + assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21"), 3); + assertEquals(new StringBuilder(ORIGIN).indexOf("A"), 0); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 3); + assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 0); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 3); + check(new StringBuilder(ORIGIN).replace(1, 3, "A"), "AA\uFF21"); + check(new StringBuilder(ORIGIN).replace(1, 4, "A"), "AA"); + check(new StringBuilder(ORIGIN).replace(1, 4, ""), "A"); + check(new StringBuilder(ORIGIN).reverse(), "\uFF21\uD801\uDC00A"); + checkSetLength(new StringBuilder(ORIGIN), 1, "A"); + check(new StringBuilder(ORIGIN).substring(0, 1), "A"); + } + + /* + * Tests for "\uD801\uDC00\uFF21A" + */ + @Test + public void testCompactStringForSupplementaryCodePointMixed2() { + final String ORIGIN = "\uD801\uDC00\uFF21A"; + assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), + Character.codePointAt(ORIGIN, 2)); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), + Character.codePointAt(ORIGIN, 0)); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), '\uD801'); + assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 2); + assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 4), 3); + check(new StringBuilder(ORIGIN).delete(0, 2), "\uFF21A"); + check(new StringBuilder(ORIGIN).delete(0, 3), "A"); + check(new StringBuilder(ORIGIN).deleteCharAt(0).deleteCharAt(0) + .deleteCharAt(0), "A"); + assertEquals(new StringBuilder(ORIGIN).indexOf("A"), 3); + assertEquals(new StringBuilder(ORIGIN).delete(0, 3).indexOf("A"), 0); + assertEquals(new StringBuilder(ORIGIN).replace(0, 3, "B").indexOf("A"), + 1); + assertEquals(new StringBuilder(ORIGIN).substring(3, 4).indexOf("A"), 0); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 2); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3); + check(new StringBuilder(ORIGIN).replace(0, 3, "B"), "BA"); + check(new StringBuilder(ORIGIN).reverse(), "A\uFF21\uD801\uDC00"); + } + + /* + * Tests for "\uD801A\uDC00\uFF21" + */ + @Test + public void testCompactStringForSupplementaryCodePointMixed3() { + final String ORIGIN = "\uD801A\uDC00\uFF21"; + assertEquals(new StringBuilder(ORIGIN).codePointAt(1), 'A'); + assertEquals(new StringBuilder(ORIGIN).codePointAt(3), '\uFF21'); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), '\uD801'); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), 'A'); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), '\uDC00'); + assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 3); + assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2); + assertEquals(new StringBuilder(ORIGIN).delete(0, 1).delete(1, 3) + .indexOf("A"), 0); + assertEquals( + new StringBuilder(ORIGIN).replace(0, 1, "B").replace(2, 4, "C") + .indexOf("A"), 1); + assertEquals(new StringBuilder(ORIGIN).substring(1, 4).substring(0, 1) + .indexOf("A"), 0); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3); + check(new StringBuilder(ORIGIN).reverse(), "\uFF21\uDC00A\uD801"); + } + + /* + * Tests for "A\uDC01\uFF21\uD801" + */ + @Test + public void testCompactStringForSupplementaryCodePointMixed4() { + final String ORIGIN = "A\uDC01\uFF21\uD801"; + assertEquals(new StringBuilder(ORIGIN).codePointAt(1), '\uDC01'); + assertEquals(new StringBuilder(ORIGIN).codePointAt(3), '\uD801'); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), 'A'); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), '\uDC01'); + assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), '\uFF21'); + assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 3); + assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2); + assertEquals(new StringBuilder(ORIGIN).delete(1, 4).indexOf("A"), 0); + assertEquals(new StringBuilder(ORIGIN).replace(1, 4, "B").indexOf("A"), + 0); + assertEquals(new StringBuilder(ORIGIN).substring(0, 1).indexOf("A"), 0); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2); + assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3); + check(new StringBuilder(ORIGIN).reverse(), "\uD801\uFF21\uDC01A"); + } + + private void checkGetChars(StringBuilder sb, int srcBegin, int srcEnd, + char expected[]) { + char[] dst = new char[srcEnd - srcBegin]; + sb.getChars(srcBegin, srcEnd, dst, 0); + assertTrue(Arrays.equals(dst, expected)); + } + + private void checkSetCharAt(StringBuilder sb, int index, char ch, + String expected) { + sb.setCharAt(index, ch); + check(sb, expected); + } + + private void checkSetLength(StringBuilder sb, int newLength, String expected) { + sb.setLength(newLength); + check(sb, expected); + } + + private void check(StringBuilder sb, String expected) { + check(sb.toString(), expected); + } + + private void check(String str, String expected) { + assertTrue(str.equals(expected), String.format( + "Get (%s) but expect (%s), ", escapeNonASCIIs(str), + escapeNonASCIIs(expected))); + } + + /* + * Because right now system default charset in JPRT environment is only + * guaranteed to support ASCII characters in log, so we escape them. + */ + private String escapeNonASCIIs(String str) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c > 0x7F) { + sb.append("\\u").append(Integer.toHexString((int) c)); + } else { + sb.append(c); + } + } + return sb.toString(); + } +} diff --git a/jdk/test/java/lang/StringBuilder/CompactStringBuilderSerialization.java b/jdk/test/java/lang/StringBuilder/CompactStringBuilderSerialization.java new file mode 100644 index 0000000000000000000000000000000000000000..0c622d78665a1726ec395eaac9f23698364c476e --- /dev/null +++ b/jdk/test/java/lang/StringBuilder/CompactStringBuilderSerialization.java @@ -0,0 +1,141 @@ +/* + * 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.io.*; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static jdk.testlibrary.SerializationUtils.*; +import static org.testng.Assert.*; + +/* + * @test + * @bug 8077559 + * @library /lib/testlibrary + * @build jdk.testlibrary.SerializationUtils + * @summary Tests Compact String. This one is testing StringBuilder serialization + * among -XX:+CompactStrings/-XX:-CompactStrings/LegacyStringBuilder + * @run testng/othervm -XX:+CompactStrings CompactStringBuilderSerialization + * @run testng/othervm -XX:-CompactStrings CompactStringBuilderSerialization + */ + +public class CompactStringBuilderSerialization { + @DataProvider + public Object[][] provider() { + return new Object[][] { + // every byte array is serialized from corresponding StringBuffer object + // by previous JDK(build 1.8.0_45-b14). + new Object[] { + new StringBuilder(""), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 0, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("A"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 1, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("AB"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 2, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, 0, 65, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("abcdefghijk"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 11, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 27, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0, + 105, 0, 106, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("\uff21"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 1, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, -1, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("\uff21\uff22"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 2, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, -1, 33, -1, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("\uff21A\uff21A\uff21A\uff21A\uff21A"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 10, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, + 33, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("A\uff21B\uff22C\uff23D\uff24E\uff25F\uff26G\uff27H\uff28"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 16, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, 0, 65, -1, 33, 0, 66, -1, 34, 0, 67, -1, 35, 0, 68, -1, 36, 0, + 69, -1, 37, 0, 70, -1, 38, 0, 71, -1, 39, 0, 72, -1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("\uff21A\uff22B\uff23C\uff24D\uff25E\uff26F\uff27G\uff28H"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 16, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, -1, 33, 0, 65, -1, 34, 0, 66, -1, 35, 0, 67, -1, 36, 0, 68, -1, + 37, 0, 69, -1, 38, 0, 70, -1, 39, 0, 71, -1, 40, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("\ud801\udc00\ud801\udc01\uff21A"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 6, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 22, -40, 1, -36, 0, -40, 1, -36, 1, -1, 33, 0, 65, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } }, + new Object[] { + new StringBuilder("\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22"), + new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105, + 108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 10, 117, 114, 0, 2, 91, 67, -80, 38, + 102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, + -1, 33, -1, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } } }; + } + + /* + * Verify serialization works between Compact StringBuilder/Legacy StringBuilder + */ + @Test(dataProvider = "provider") + public void test(StringBuilder sbContent, byte[] baInJDK8) throws Exception { + // Serialize a StringBuilder object into byte array. + byte[] ba = serialize(sbContent); + assertEquals(ba, baInJDK8); + // Deserialize a StringBuilder object from byte array which is generated by previous JDK(build 1.8.0_45-b14). + Object obj = deserialize(ba); + assertEquals(obj.getClass(), StringBuilder.class); + assertTrue(equals((StringBuilder)obj, sbContent)); + } + + boolean equals(StringBuilder sb, StringBuilder expected) { + if(sb.length() == expected.length() + && sb.capacity() == expected.capacity() + && sb.toString().equals(expected.toString())) { + return true; + } + return false; + } +} diff --git a/jdk/test/java/lang/StringBuilder/Exceptions.java b/jdk/test/java/lang/StringBuilder/Exceptions.java index e1686b010910040bf2df434b97e4c1bb432aee7e..bee53bcea92344c511ec0eafeaabc58a7892bc64 100644 --- a/jdk/test/java/lang/StringBuilder/Exceptions.java +++ b/jdk/test/java/lang/StringBuilder/Exceptions.java @@ -94,21 +94,21 @@ public class Exceptions { System.out.println("StringBuilder.replace(int start, int end, String str)"); tryCatch(" -1, 2, \" \"", - new StringIndexOutOfBoundsException(-1), + new StringIndexOutOfBoundsException("start -1, end 2, length 7"), new Runnable() { public void run() { StringBuilder sb = new StringBuilder("hilbert"); sb.replace(-1, 2, " "); }}); tryCatch(" 7, 8, \" \"", - new StringIndexOutOfBoundsException("start > length()"), + new StringIndexOutOfBoundsException("start 7, end 6, length 6"), new Runnable() { public void run() { StringBuilder sb = new StringBuilder("banach"); sb.replace(7, 8, " "); }}); tryCatch(" 2, 1, \" \"", - new StringIndexOutOfBoundsException("start > end"), + new StringIndexOutOfBoundsException("start 2, end 1, length 7"), new Runnable() { public void run() { StringBuilder sb = new StringBuilder("riemann"); diff --git a/jdk/test/java/security/SecureRandom/DefaultProvider.java b/jdk/test/java/security/SecureRandom/DefaultProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..50b4719acc620a22d549e5983fd89ce8c9bf74ec --- /dev/null +++ b/jdk/test/java/security/SecureRandom/DefaultProvider.java @@ -0,0 +1,110 @@ +/* + * 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 static java.lang.System.out; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * @test + * @bug 8048356 + * @summary Assert default provider used on all OS for SecureRandom + */ +public class DefaultProvider { + + private static final String OS_NAME = System.getProperty("os.name"); + private static final String SUNOS = "SunOS"; + private static final String WINDOWS = "Windows"; + + public static void main(String[] args) throws NoSuchAlgorithmException { + out.println("Operating System: " + OS_NAME); + + /* Test default provider used with constructor */ + out.println("TEST: Default provider with constructor"); + SecureRandom secureRandom = new SecureRandom(); + String provider = secureRandom.getProvider().getName(); + if (OS_NAME.startsWith(SUNOS)) { + if (!provider.startsWith("SunPKCS11-")) { + throw new RuntimeException("Unexpected provider name: " + + provider); + } + } else if (!provider.equals("SUN")) { + throw new RuntimeException("Unexpected provider name: " + + provider); + } + out.println("Passed, default provider with constructor: " + provider); + + /* Test default provider with getInstance(String algorithm) */ + out.println("TEST: SHA1PRNG supported on all platforms by SUN provider"); + String algorithm = "SHA1PRNG"; + provider = "SUN"; + + SecureRandom instance = SecureRandom.getInstance(algorithm); + assertInstance(instance, algorithm, provider); + out.println("Passed."); + + if (!OS_NAME.startsWith(WINDOWS)) { + out.println("TEST: NativePRNG supported on all platforms" + + "(except Windows), by SUN provider"); + algorithm = "NativePRNG"; + provider = "SUN"; + } else { + out.println( + "TEST: Windows-PRNG supported on windows by SunMSCAPI provider"); + algorithm = "Windows-PRNG"; + provider = "SunMSCAPI"; + } + instance = SecureRandom.getInstance(algorithm); + assertInstance(instance, algorithm, provider); + out.println("Passed."); + + if (OS_NAME.startsWith(SUNOS)) { + out.println( + "TEST: PKCS11 is supported on Solaris by SunPKCS11 provider"); + algorithm = "PKCS11"; + provider = "SunPKCS11-Solaris"; + instance = SecureRandom.getInstance(algorithm); + assertInstance(instance, algorithm, provider); + out.println("Passed."); + } + } + + private static void assertInstance(SecureRandom instance, + String expectedAlgorithm, + String expectedProvider) { + if (instance != null) { + if (!expectedAlgorithm.equalsIgnoreCase(instance.getAlgorithm())) { + throw new RuntimeException("Expected algorithm:" + + expectedAlgorithm + " actual: " + instance.getAlgorithm()); + } + + if (!expectedProvider.equalsIgnoreCase(instance.getProvider().getName())) { + throw new RuntimeException("Expected provider: " + + expectedProvider + " actual: " + + instance.getProvider().getName()); + } + } else { + throw new RuntimeException("Secure instance is not created"); + } + } +} diff --git a/jdk/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java b/jdk/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java index 11e2dcd96207c8a392620120ba2da8897d1a88fe..c1656885c07c6296f9e0b5356a388d04ce5e108d 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java +++ b/jdk/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java @@ -156,6 +156,7 @@ public class TCKZoneIdPrinterParser { {"UTC", 3, -1, ZoneId.of("UTC"), false}, {"UT", 2, -1, ZoneId.of("UT"), false}, {"GMT", 3, -1, ZoneId.of("GMT"), false}, + {"GMT0", 4, -1, ZoneId.of("GMT0"), false}, {"+00:00", 6, -1, ZoneOffset.UTC, true}, {"UTC+00:00", 9, -1, ZoneId.of("UTC"), false}, diff --git a/jdk/test/java/time/test/java/time/temporal/TestIsoWeekFields.java b/jdk/test/java/time/test/java/time/temporal/TestIsoWeekFields.java index d79d13f89a399b924be261d2dd2490e4bac75adf..672295e4defff5124e5881cf3c591749a899905e 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestIsoWeekFields.java +++ b/jdk/test/java/time/test/java/time/temporal/TestIsoWeekFields.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 @@ -121,6 +121,14 @@ public class TestIsoWeekFields { assertEquals(IsoFields.WEEK_BASED_YEAR.isSupportedBy(ThaiBuddhistDate.now()), false); } + @Test + public void test_Unit_isSupportedBy_ISO() { + assertEquals(IsoFields.WEEK_BASED_YEARS.isSupportedBy(LocalDate.now()),true); + assertEquals(IsoFields.WEEK_BASED_YEARS.isSupportedBy(ThaiBuddhistDate.now()),false); + assertEquals(IsoFields.QUARTER_YEARS.isSupportedBy(LocalDate.now()),true); + assertEquals(IsoFields.QUARTER_YEARS.isSupportedBy(ThaiBuddhistDate.now()),false); + } + @Test(dataProvider = "fields") public void test_WBY_range(TemporalField weekField, TemporalField yearField) { assertEquals(yearField.range(), ValueRange.of(Year.MIN_VALUE, Year.MAX_VALUE)); diff --git a/jdk/test/java/util/Objects/BasicObjectsTest.java b/jdk/test/java/util/Objects/BasicObjectsTest.java index 878bb8250197acd760813ca02ae8f8a9c341ee89..a7636ef11d52b91b99e0af2c9a888955c30b40fe 100644 --- a/jdk/test/java/util/Objects/BasicObjectsTest.java +++ b/jdk/test/java/util/Objects/BasicObjectsTest.java @@ -241,12 +241,12 @@ public class BasicObjectsTest { String nonNullString = "non-null"; // Confirm the compile time return type matches - String result = Objects.nonNullElse(nullString, defString); + String result = Objects.requireNonNullElse(nullString, defString); errors += (result == defString) ? 0 : 1; - errors += (Objects.nonNullElse(nonNullString, defString) == nonNullString) ? 0 : 1; - errors += (Objects.nonNullElse(nonNullString, null) == nonNullString) ? 0 : 1; + errors += (Objects.requireNonNullElse(nonNullString, defString) == nonNullString) ? 0 : 1; + errors += (Objects.requireNonNullElse(nonNullString, null) == nonNullString) ? 0 : 1; try { - Objects.nonNullElse(null, null); + Objects.requireNonNullElse(null, null); errors += 1; } catch (NullPointerException npe) { // expected @@ -254,20 +254,20 @@ public class BasicObjectsTest { } - // Test nonNullElseGet with a supplier - errors += (Objects.nonNullElseGet(nullString, () -> defString) == defString) ? 0 : 1; - errors += (Objects.nonNullElseGet(nonNullString, () -> defString) == nonNullString) ? 0 : 1; - errors += (Objects.nonNullElseGet(nonNullString, () -> null) == nonNullString) ? 0 : 1; + // Test requireNonNullElseGet with a supplier + errors += (Objects.requireNonNullElseGet(nullString, () -> defString) == defString) ? 0 : 1; + errors += (Objects.requireNonNullElseGet(nonNullString, () -> defString) == nonNullString) ? 0 : 1; + errors += (Objects.requireNonNullElseGet(nonNullString, () -> null) == nonNullString) ? 0 : 1; try { - Objects.nonNullElseGet(null, () -> null); + Objects.requireNonNullElseGet(null, () -> null); errors += 1; } catch (NullPointerException npe) { // expected errors += npe.getMessage().equals("supplier.get()") ? 0 : 1; } try { // supplier is null - Objects.nonNullElseGet(null, null); + Objects.requireNonNullElseGet(null, null); errors += 1; } catch (NullPointerException npe) { // expected diff --git a/jdk/test/java/util/concurrent/Phaser/Basic.java b/jdk/test/java/util/concurrent/Phaser/Basic.java index 401b983e189f5362c0cff8bdaa176773f1dbcdc6..c516a969b398eb91d4a8edb8c147cca964fc0c70 100644 --- a/jdk/test/java/util/concurrent/Phaser/Basic.java +++ b/jdk/test/java/util/concurrent/Phaser/Basic.java @@ -34,6 +34,7 @@ /* * @test * @bug 6445158 + * @key intermittent * @summary Basic tests for Phaser * @author Chris Hegarty */ diff --git a/jdk/test/java/util/zip/TestLocalTime.java b/jdk/test/java/util/zip/TestLocalTime.java index 47d3e81d226cfbbf289323cc107d3ec6c83de79e..d1909afba54843c8c28fd4819894be83f09db2cd 100644 --- a/jdk/test/java/util/zip/TestLocalTime.java +++ b/jdk/test/java/util/zip/TestLocalTime.java @@ -21,9 +21,10 @@ * questions. */ -/** +/* * @test * @bug 8075526 + * @key intermittent * @summary Test timestamp via ZipEntry.get/setTimeLocal() */ diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/SerializationUtils.java b/jdk/test/lib/testlibrary/jdk/testlibrary/SerializationUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..3dbc66692dbb3e65542b5bd3fd7746bfb5a768aa --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/SerializationUtils.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. + */ + +package jdk.testlibrary; + +import java.io.*; + +/** + * Common library for various test serialization utility functions. + */ +public final class SerializationUtils { + /* + * Serialize an object into byte array. + */ + public static byte[] serialize(Object obj) throws Exception { + try (ByteArrayOutputStream bs = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bs);) { + out.writeObject(obj); + return bs.toByteArray(); + } + } + + /* + * Deserialize an object from byte array. + */ + public static Object deserialize(byte[] ba) throws Exception { + try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(ba));) { + return in.readObject(); + } + } +} diff --git a/jdk/test/sun/nio/cs/TestStringCoding.java b/jdk/test/sun/nio/cs/TestStringCoding.java index f9f7021dca3826136d297eb54c8c468f66cb7ea0..4dd85f490a310c1fca649845eb22b4036cdcb875 100644 --- a/jdk/test/sun/nio/cs/TestStringCoding.java +++ b/jdk/test/sun/nio/cs/TestStringCoding.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 6636323 6636319 7040220 7096080 7183053 8080248 + * @bug 6636323 6636319 7040220 7096080 7183053 8080248 8054307 * @summary Test if StringCoding and NIO result have the same de/encoding result * @modules java.base/sun.nio.cs * @run main/othervm/timeout=2000 TestStringCoding @@ -36,41 +36,61 @@ import java.nio.charset.*; public class TestStringCoding { public static void main(String[] args) throws Throwable { + // full bmp first + char[] bmp = new char[0x10000]; + for (int i = 0; i < 0x10000; i++) { + bmp[i] = (char)i; + } + char[] latin = Arrays.copyOf(bmp, 0x100); + char[] ascii = Arrays.copyOf(bmp, 0x80); + + byte[] latinBA = new byte[0x100]; + for (int i = 0; i < 0x100; i++) { + latinBA[i] = (byte)i; + } + byte[] asciiBA = Arrays.copyOf(latinBA, 0x80); + for (Boolean hasSM: new boolean[] { false, true }) { - if (hasSM) + if (hasSM) { System.setSecurityManager(new PermissiveSecurityManger()); + } for (Charset cs: Charset.availableCharsets().values()) { if ("ISO-2022-CN".equals(cs.name()) || "x-COMPOUND_TEXT".equals(cs.name()) || "x-JISAutoDetect".equals(cs.name())) continue; System.out.printf("Testing(sm=%b) " + cs.name() + "....", hasSM); - // full bmp first - char[] bmpCA = new char[0x10000]; - for (int i = 0; i < 0x10000; i++) { - bmpCA[i] = (char)i; - } - byte[] sbBA = new byte[0x100]; - for (int i = 0; i < 0x100; i++) { - sbBA[i] = (byte)i; - } - test(cs, bmpCA, sbBA); + + testNewString(cs, testGetBytes(cs, new String(bmp))); + testNewString(cs, testGetBytes(cs, new String(latin))); + testNewString(cs, testGetBytes(cs, new String(ascii))); + testGetBytes(cs, testNewString(cs, latinBA)); + testGetBytes(cs, testNewString(cs, asciiBA)); + // "randomed" sizes Random rnd = new Random(); for (int i = 0; i < 10; i++) { - int clen = rnd.nextInt(0x10000); - int blen = rnd.nextInt(0x100); //System.out.printf(" blen=%d, clen=%d%n", blen, clen); - test(cs, Arrays.copyOf(bmpCA, clen), Arrays.copyOf(sbBA, blen)); + char[] bmp0 = Arrays.copyOf(bmp, rnd.nextInt(0x10000)); + testNewString(cs, testGetBytes(cs, new String(bmp0))); //add a pair of surrogates - int pos = clen / 2; - if ((pos + 1) < blen) { - bmpCA[pos] = '\uD800'; - bmpCA[pos+1] = '\uDC00'; + int pos = bmp0.length / 2; + if ((pos + 1) < bmp0.length) { + bmp0[pos] = '\uD800'; + bmp0[pos+1] = '\uDC00'; } - test(cs, Arrays.copyOf(bmpCA, clen), Arrays.copyOf(sbBA, blen)); + testNewString(cs, testGetBytes(cs, new String(bmp0))); + + char[] latin0 = Arrays.copyOf(latin, rnd.nextInt(0x100)); + char[] ascii0 = Arrays.copyOf(ascii, rnd.nextInt(0x80)); + byte[] latinBA0 = Arrays.copyOf(latinBA, rnd.nextInt(0x100)); + byte[] asciiBA0 = Arrays.copyOf(asciiBA, rnd.nextInt(0x80)); + testNewString(cs, testGetBytes(cs, new String(latin0))); + testNewString(cs, testGetBytes(cs, new String(ascii0))); + testGetBytes(cs, testNewString(cs, latinBA0)); + testGetBytes(cs, testNewString(cs, asciiBA0)); } - + testSurrogates(cs); testMixed(cs); System.out.println("done!"); } @@ -109,8 +129,9 @@ public class TestStringCoding { //getBytes(cs); bmpBA = bmpStr.getBytes(cs); - if (!Arrays.equals(bmpBA, baNIO)) + if (!Arrays.equals(bmpBA, baNIO)) { throw new RuntimeException("getBytes(cs) failed -> " + cs.name()); + } //new String(csn); String strSC = new String(bmpBA, cs.name()); @@ -118,49 +139,61 @@ public class TestStringCoding { if(!strNIO.equals(strSC)) { throw new RuntimeException("new String(csn) failed -> " + cs.name()); } - //new String(cs); strSC = new String(bmpBA, cs); - if (!strNIO.equals(strSC)) + if (!strNIO.equals(strSC)) { throw new RuntimeException("new String(cs) failed -> " + cs.name()); + } + } + static byte[] getBytes(CharsetEncoder enc, String str) throws Throwable { + ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(str.toCharArray())); + byte[] ba = new byte[bf.limit()]; + bf.get(ba, 0, ba.length); + return ba; } - static void test(Charset cs, char[] bmpCA, byte[] sbBA) throws Throwable { - String bmpStr = new String(bmpCA); - CharsetDecoder dec = cs.newDecoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); + static byte[] testGetBytes(Charset cs, String str) throws Throwable { CharsetEncoder enc = cs.newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); - //getBytes(csn); - byte[] baSC = bmpStr.getBytes(cs.name()); - ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(bmpCA)); - byte[] baNIO = new byte[bf.limit()]; - bf.get(baNIO, 0, baNIO.length); - if (!Arrays.equals(baSC, baNIO)) + byte[] baSC = str.getBytes(cs.name()); + byte[] baNIO = getBytes(enc, str); + if (!Arrays.equals(baSC, baNIO)) { throw new RuntimeException("getBytes(csn) failed -> " + cs.name()); - + } //getBytes(cs); - baSC = bmpStr.getBytes(cs); - if (!Arrays.equals(baSC, baNIO)) + baSC = str.getBytes(cs); + if (!Arrays.equals(baSC, baNIO)) { throw new RuntimeException("getBytes(cs) failed -> " + cs.name()); + } + return baSC; + } + static String testNewString(Charset cs, byte[] ba) throws Throwable { + CharsetDecoder dec = cs.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); //new String(csn); - String strSC = new String(sbBA, cs.name()); - String strNIO = dec.reset().decode(ByteBuffer.wrap(sbBA)).toString(); - - if(!strNIO.equals(strSC)) + String strSC = new String(ba, cs.name()); + String strNIO = dec.reset().decode(ByteBuffer.wrap(ba)).toString(); + if(!strNIO.equals(strSC)) { throw new RuntimeException("new String(csn) failed -> " + cs.name()); - + } //new String(cs); - strSC = new String(sbBA, cs); - if (!strNIO.equals(strSC)) - throw new RuntimeException("new String(cs) failed -> " + cs.name()); + strSC = new String(ba, cs); + if (!strNIO.equals(strSC)) { + throw new RuntimeException("new String(cs)/bmp failed -> " + cs.name()); + } + return strSC; + } + static void testSurrogates(Charset cs) throws Throwable { //encode unmappable surrogates + CharsetEncoder enc = cs.newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); if (enc instanceof sun.nio.cs.ArrayEncoder && cs.contains(Charset.forName("ASCII"))) { if (cs.name().equals("UTF-8") || // utf8 handles surrogates diff --git a/jdk/test/sun/nio/cs/TestStringCodingUTF8.java b/jdk/test/sun/nio/cs/TestStringCodingUTF8.java index b936838ea13045a44e89e740beb25531ba072463..ad07f19a6a361fa578cdd10363ccffb588f47c65 100644 --- a/jdk/test/sun/nio/cs/TestStringCodingUTF8.java +++ b/jdk/test/sun/nio/cs/TestStringCodingUTF8.java @@ -22,7 +22,7 @@ */ /* @test - @bug 7040220 + @bug 7040220 8054307 @summary Test if StringCoding and NIO result have the same de/encoding result for UTF-8 * @run main/othervm/timeout=2000 TestStringCodingUTF8 * @key randomness @@ -50,6 +50,18 @@ public class TestStringCodingUTF8 { } test(cs, bmp, 0, bmp.length); + char[] ascii = new char[0x80]; + for (int i = 0; i < 0x80; i++) { + ascii[i] = (char)i; + } + test(cs, ascii, 0, ascii.length); + + char[] latin1 = new char[0x100]; + for (int i = 0; i < 0x100; i++) { + latin1[i] = (char)i; + } + test(cs, latin1, 0, latin1.length); + ArrayList<Integer> list = new ArrayList<>(0x20000); for (int i = 0; i < 0x20000; i++) { list.add(i, i); diff --git a/jdk/test/sun/security/jca/PreferredProviderNegativeTest.java b/jdk/test/sun/security/jca/PreferredProviderNegativeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5d69d998eb9315794fb2ecf005c13e9f4a4d5df2 --- /dev/null +++ b/jdk/test/sun/security/jca/PreferredProviderNegativeTest.java @@ -0,0 +1,130 @@ +/* + * 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 8076359 8133151 + * @summary Test for jdk.security.provider.preferred security property + * @requires os.name == "SunOS" + * @run main/othervm PreferredProviderNegativeTest preJCESet AES:OracleUcrypto false + * @run main/othervm PreferredProviderNegativeTest preJCESet AES:SunNegative true + * @run main/othervm PreferredProviderNegativeTest afterJCESet AES:SunJGSS + * @run main/othervm PreferredProviderNegativeTest afterJCESet AES:SunECNegative + * @run main/othervm PreferredProviderNegativeTest invalidAlg AESNegative:SunJCE + */ + +import java.security.Security; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; + +public class PreferredProviderNegativeTest { + + /* + * Test security property could be set by valid and invalid provider + * before JCE was loaded + */ + public static void preJCESet(String value, boolean negativeProvider) + throws NoSuchAlgorithmException, NoSuchPaddingException { + Security.setProperty("jdk.security.provider.preferred", value); + + if (!Security.getProperty("jdk.security.provider.preferred") + .equals(value)) { + throw new RuntimeException( + "Test Failed:The property wasn't set"); + } + + String[] arrays = value.split(":"); + Cipher cipher = Cipher.getInstance(arrays[0]); + + if (negativeProvider) { + if (cipher.getProvider().getName().equals(arrays[1])) { + throw new RuntimeException( + "Test Failed:The provider shouldn't be set"); + } + } else { + if (!cipher.getProvider().getName().equals(arrays[1])) { + throw new RuntimeException( + "Test Faild:The provider could be set " + + "by valid provider "); + } + } + System.out.println("Test Pass"); + } + + /* + * Test that the setting of the security property after Cipher.getInstance() + * does not influence previously loaded instances + */ + public static void afterJCESet(String value) + throws NoSuchAlgorithmException, NoSuchPaddingException { + String[] arrays = value.split(":"); + Cipher cipher = Cipher.getInstance(arrays[0]); + + Security.setProperty("jdk.security.provider.preferred", value); + if (!cipher.getProvider().getName().equals("SunJCE")) { + throw new RuntimeException( + "Test Failed:The security property can't be updated after JCE load."); + } + System.out.println("Test Pass"); + } + + /* Test the security property with negative algorithm */ + public static void invalidAlg(String value) throws NoSuchPaddingException { + String[] arrays = value.split(":"); + + try { + Security.setProperty("jdk.security.provider.preferred", value); + Cipher.getInstance(arrays[0]); + } catch (NoSuchAlgorithmException e) { + System.out.println("Test Pass:Got NoSuchAlgorithmException as expired"); + return; + } + throw new RuntimeException( + "Test Failed:Expected NoSuchAlgorithmException was not thrown"); + } + + public static void main(String[] args) + throws NoSuchAlgorithmException, NoSuchPaddingException { + boolean negativeProvider; + + if (args.length >= 2) { + switch (args[0]) { + case "preJCESet": + negativeProvider = Boolean.valueOf(args[2]); + PreferredProviderNegativeTest.preJCESet(args[1], negativeProvider); + break; + case "afterJCESet": + PreferredProviderNegativeTest.afterJCESet(args[1]); + break; + case "invalidAlg": + PreferredProviderNegativeTest.invalidAlg(args[1]); + break; + } + } else { + throw new RuntimeException( + "Test Failed:Please pass the correct args"); + } + } +} + diff --git a/jdk/test/sun/security/jca/PreferredProviderTest.java b/jdk/test/sun/security/jca/PreferredProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7120817a1b57cada18fc36b1e710b608ad3ea22d --- /dev/null +++ b/jdk/test/sun/security/jca/PreferredProviderTest.java @@ -0,0 +1,131 @@ +/* + * 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 8076359 8133151 + * @summary Test the value for new jdk.security.provider.preferred security property + * @requires os.name == "SunOS" + */ + +import java.security.KeyFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; +import java.util.Arrays; +import java.util.List; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; + +public class PreferredProviderTest { + + private static final List<DataTuple> SPARC_DATA = Arrays.asList( + new DataTuple("SHA-256", "SUN"), new DataTuple("SHA-384", "SUN"), + new DataTuple("SHA-512", "SUN")); + private static final List<DataTuple> X86_DATA = Arrays + .asList(new DataTuple("RSA", "SunRsaSign")); + + public void RunTest(String type) + throws NoSuchAlgorithmException, NoSuchPaddingException { + String preferredProvider = Security + .getProperty("jdk.security.provider.preferred"); + String actualProvider = null; + if (type.equals("sparcv9")) { + if (!preferredProvider.equals( + "AES:SunJCE, SHA-256:SUN, SHA-384:SUN, SHA-512:SUN")) { + throw new RuntimeException( + "Test Failed: wrong jdk.security.provider.preferred " + + "value on solaris-sparcv9"); + } + for (DataTuple dataTuple : SPARC_DATA) { + MessageDigest md = MessageDigest + .getInstance(dataTuple.algorithm); + actualProvider = md.getProvider().getName(); + if (!actualProvider.equals(dataTuple.provider)) { + throw new RuntimeException(String.format( + "Test Failed:Got wrong " + + "provider from Solaris-sparcv9 platform," + + "Expected Provider: %s, Returned Provider: %s", + dataTuple.provider, actualProvider)); + } + } + } else if (type.equals("amd64")) { + if (!preferredProvider.equals("AES:SunJCE, RSA:SunRsaSign")) { + throw new RuntimeException( + "Test Failed: wrong jdk.security.provider.preferred " + + "value on solaris-x86"); + } + for (DataTuple dataTuple : X86_DATA) { + KeyFactory keyFactory = KeyFactory + .getInstance(dataTuple.algorithm); + actualProvider = keyFactory.getProvider().getName(); + if (!actualProvider.equals(dataTuple.provider)) { + throw new RuntimeException(String.format( + "Test Failed:Got wrong " + + "provider from Solaris-x86 platform," + + "Expected Provider: %s, Returned Provider: %s", + dataTuple.provider, actualProvider)); + } + } + } else { + throw new RuntimeException("Test Failed: wrong platform value"); + } + + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + actualProvider = cipher.getProvider().getName(); + if (!actualProvider.equals("SunJCE")) { + throw new RuntimeException(String.format( + "Test Failed:Got wrong provider from Solaris-%s platform, " + + "Expected Provider: SunJCE, Returned Provider: %s", + type, actualProvider)); + } + + MessageDigest md = MessageDigest.getInstance("MD5"); + actualProvider = md.getProvider().getName(); + if (!actualProvider.equals("OracleUcrypto")) { + throw new RuntimeException(String.format( + "Test Failed:Got wrong provider from Solaris-%s platform," + + "Expected Provider: OracleUcrypto, Returned Provider: %s", + type, actualProvider)); + } + } + + private static class DataTuple { + private final String provider; + private final String algorithm; + + private DataTuple(String algorithm, String provider) { + this.algorithm = algorithm; + this.provider = provider; + } + } + + public static void main(String[] args) + throws NoSuchAlgorithmException, NoSuchPaddingException { + + String arch = System.getProperty("os.arch"); + PreferredProviderTest pp = new PreferredProviderTest(); + pp.RunTest(arch); + } +} + diff --git a/langtools/.hgtags b/langtools/.hgtags index 1a826fd56024115b9325f35d39cdb4236adde026..1cafcfb9b090c84596d0ec6d2f396fcd0b6c41b1 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -334,3 +334,4 @@ ac57d80b205db48d726084ade228e0199735831b jdk9-b88 16873e56156e9917ad97ba5da0d0abe44fc94003 jdk9-b89 00a25f93cee8a82096a0736716da392cafdb0cb0 jdk9-b90 79501a97ca5720af846509f4bf3c6c04d7bdf82a jdk9-b91 +a3415b57507c928af8f2ad1c771eebafcd00c6c7 jdk9-b92 diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java index 3bbd7175cf96dc15edfa483e685f8f8d28d77b16..02cf1242ace60b3cd914f3eeca4e71c407362ac7 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java @@ -126,10 +126,9 @@ public class Flags { */ public static final int BLOCK = 1<<20; - /** Flag is set for compiler-generated abstract methods that implement - * an interface method (Miranda methods). + /** Flag bit 21 is available. (used earlier to tag compiler-generated abstract methods that implement + * an interface method (Miranda methods)). */ - public static final int IPROXY = 1<<21; /** Flag is set for nested classes that do not access instance members * or `this' of an outer class and therefore don't need to be passed @@ -362,7 +361,6 @@ public class Flags { BLOCK(Flags.BLOCK), ENUM(Flags.ENUM), MANDATED(Flags.MANDATED), - IPROXY(Flags.IPROXY), NOOUTERTHIS(Flags.NOOUTERTHIS), EXISTS(Flags.EXISTS), COMPOUND(Flags.COMPOUND), diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index f272aa3bf3a71fa1b0d73987c8d9f1da35517aed..0fbe7da988adcd36a81e5e65ac242d4e5cc6b3b6 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -180,6 +180,14 @@ public abstract class Symbol extends AnnoConstruct implements Element { : metadata.getInitTypeAttributes(); } + public void setInitTypeAttributes(List<Attribute.TypeCompound> l) { + initedMetadata().setInitTypeAttributes(l); + } + + public void setClassInitTypeAttributes(List<Attribute.TypeCompound> l) { + initedMetadata().setClassInitTypeAttributes(l); + } + public List<Attribute.Compound> getDeclarationAttributes() { return (metadata == null) ? List.<Attribute.Compound>nil() diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java index 4bc4fc6ddfde49fcfe3c89ae74fd068165b9e545..14318bba74e77ae23ef8055efa07ab48f084301e 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java @@ -32,6 +32,7 @@ import javax.tools.JavaFileObject; import com.sun.tools.javac.code.Attribute.Array; import com.sun.tools.javac.code.Attribute.TypeCompound; +import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.CapturedType; @@ -388,8 +389,21 @@ public class TypeAnnotations { sym.getKind() == ElementKind.RESOURCE_VARIABLE || sym.getKind() == ElementKind.EXCEPTION_PARAMETER) { // Make sure all type annotations from the symbol are also - // on the owner. - sym.owner.appendUniqueTypeAttributes(sym.getRawTypeAttributes()); + // on the owner. If the owner is an initializer block, propagate + // to the type. + final long ownerFlags = sym.owner.flags(); + if ((ownerFlags & Flags.BLOCK) != 0) { + // Store init and clinit type annotations with the ClassSymbol + // to allow output in Gen.normalizeDefs. + ClassSymbol cs = (ClassSymbol) sym.owner.owner; + if ((ownerFlags & Flags.STATIC) != 0) { + cs.appendClassInitTypeAttributes(typeAnnotations); + } else { + cs.appendInitTypeAttributes(typeAnnotations); + } + } else { + sym.owner.appendUniqueTypeAttributes(sym.getRawTypeAttributes()); + } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index 13136d79e3f8ce303e5353a975f281abd7358b39..9f02b1739231629df0f30627c48cb3f40d818bef 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -2763,7 +2763,7 @@ public class Types { Scope s = c.members(); for (Symbol sym : s.getSymbols(NON_RECURSIVE)) { if (sym.kind == MTH && - (sym.flags() & (ABSTRACT|IPROXY|DEFAULT|PRIVATE)) == ABSTRACT) { + (sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) { MethodSymbol absmeth = (MethodSymbol)sym; MethodSymbol implmeth = absmeth.implementation(impl, this, true); if (implmeth == null || implmeth == absmeth) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 76666ce53132ec6ad1cfa92ae766e2c64cfc60d6..862d54a3ea81a1bfc3fbd3cbfb7405efe1416d1c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1890,7 +1890,8 @@ public class Attr extends JCTree.Visitor { // Check that value of resulting type is admissible in the // current context. Also, capture the return type - result = check(tree, capture(restype), KindSelector.VAL, resultInfo); + Type capturedRes = resultInfo.checkContext.inferenceContext().cachedCapture(tree, restype, true); + result = check(tree, capturedRes, KindSelector.VAL, resultInfo); } chk.validate(tree.typeargs, localEnv); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index 001443e05799f6e4af0d2a15845fe8904c7bd8bc..fc62e8a7865c0b03f42243b57d73419c613bc743 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -1730,11 +1730,18 @@ public class Check { boolean resultTypesOK = types.returnTypeSubstitutable(mt, ot, otres, overrideWarner); if (!resultTypesOK) { - log.error(TreeInfo.diagnosticPositionFor(m, tree), - "override.incompatible.ret", - cannotOverride(m, other), - mtres, otres); - m.flags_field |= BAD_OVERRIDE; + if ((m.flags() & STATIC) != 0 && (other.flags() & STATIC) != 0) { + log.error(TreeInfo.diagnosticPositionFor(m, tree), + Errors.OverrideIncompatibleRet(Fragments.CantHide(m, m.location(), other, + other.location()), mtres, otres)); + m.flags_field |= BAD_OVERRIDE; + } else { + log.error(TreeInfo.diagnosticPositionFor(m, tree), + "override.incompatible.ret", + cannotOverride(m, other), + mtres, otres); + m.flags_field |= BAD_OVERRIDE; + } return; } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) { warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), @@ -2371,7 +2378,6 @@ public class Check { types.isSameType(types.erasure(sym.type), types.erasure(sym2.type)) && sym != sym2 && (sym.flags() & Flags.SYNTHETIC) != (sym2.flags() & Flags.SYNTHETIC) && - (sym.flags() & IPROXY) == 0 && (sym2.flags() & IPROXY) == 0 && (sym.flags() & BRIDGE) == 0 && (sym2.flags() & BRIDGE) == 0) { syntheticError(pos, (sym2.flags() & SYNTHETIC) == 0 ? sym2 : sym); return; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java index fa61200d21eac0f83b1d4aada0a06ff243a1e83d..99d01109e7665a1baf46519729bf3116166ef474 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java @@ -372,6 +372,9 @@ public class Infer { resultInfo, inferenceContext); } } + } else if (rsInfoInfContext.free(resultInfo.pt)) { + //propagation - cache captured vars + qtype = inferenceContext.asUndetVar(rsInfoInfContext.cachedCapture(tree, from, false)); } Assert.check(allowGraphInference || !rsInfoInfContext.free(to), "legacy inference engine cannot handle constraints on both sides of a subtyping assertion"); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index d8072920f6036a11a61c46b210665b3f90635831..63ed6b8995089f56f13afd61741aa95e76b091bf 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -55,12 +55,16 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Supplier; import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.tree.JCTree.Tag.*; + +import javax.lang.model.element.ElementKind; import javax.lang.model.type.TypeKind; /** @@ -268,21 +272,34 @@ public class LambdaToMethod extends TreeTranslator { MethodSymbol sym = localContext.translatedSym; MethodType lambdaType = (MethodType) sym.type; - { + { /* Type annotation management: Based on where the lambda features, type annotations that + are interior to it, may at this point be attached to the enclosing method, or the first + constructor in the class, or in the enclosing class symbol or in the field whose + initializer is the lambda. In any event, gather up the annotations that belong to the + lambda and attach it to the implementation method. + */ + Symbol owner = localContext.owner; - ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>(); - ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>(); + apportionTypeAnnotations(tree, + owner::getRawTypeAttributes, + owner::setTypeAttributes, + sym::setTypeAttributes); - for (Attribute.TypeCompound tc : owner.getRawTypeAttributes()) { - if (tc.position.onLambda == tree) { - lambdaTypeAnnos.append(tc); - } else { - ownerTypeAnnos.append(tc); - } + + boolean init; + if ((init = (owner.name == names.init)) || owner.name == names.clinit) { + owner = owner.owner; + apportionTypeAnnotations(tree, + init ? owner::getInitTypeAttributes : owner::getClassInitTypeAttributes, + init ? owner::setInitTypeAttributes : owner::setClassInitTypeAttributes, + sym::appendUniqueTypeAttributes); } - if (lambdaTypeAnnos.nonEmpty()) { - owner.setTypeAttributes(ownerTypeAnnos.toList()); - sym.setTypeAttributes(lambdaTypeAnnos.toList()); + if (localContext.self != null && localContext.self.getKind() == ElementKind.FIELD) { + owner = localContext.self; + apportionTypeAnnotations(tree, + owner::getRawTypeAttributes, + owner::setTypeAttributes, + sym::appendUniqueTypeAttributes); } } @@ -338,6 +355,11 @@ public class LambdaToMethod extends TreeTranslator { syntheticInits.append((JCExpression) captured_local); } } + // add captured outer this instances (used only when `this' capture itself is illegal) + for (Symbol fv : localContext.getSymbolMap(CAPTURED_OUTER_THIS).keySet()) { + JCTree captured_local = make.QualThis(fv.type); + syntheticInits.append((JCExpression) captured_local); + } //then, determine the arguments to the indy call List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev); @@ -349,6 +371,29 @@ public class LambdaToMethod extends TreeTranslator { result = makeMetafactoryIndyCall(context, refKind, sym, indy_args); } + // where + // Reassign type annotations from the source that should really belong to the lambda + private void apportionTypeAnnotations(JCLambda tree, + Supplier<List<Attribute.TypeCompound>> source, + Consumer<List<Attribute.TypeCompound>> owner, + Consumer<List<Attribute.TypeCompound>> lambda) { + + ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>(); + ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>(); + + for (Attribute.TypeCompound tc : source.get()) { + if (tc.position.onLambda == tree) { + lambdaTypeAnnos.append(tc); + } else { + ownerTypeAnnos.append(tc); + } + } + if (lambdaTypeAnnos.nonEmpty()) { + owner.accept(ownerTypeAnnos.toList()); + lambda.accept(lambdaTypeAnnos.toList()); + } + } + private JCIdent makeThis(Type type, Symbol owner) { VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC, names._this, @@ -434,6 +479,32 @@ public class LambdaToMethod extends TreeTranslator { } } + /** + * Translate qualified `this' references within a lambda to the mapped identifier + * @param tree + */ + @Override + public void visitSelect(JCFieldAccess tree) { + if (context == null || !analyzer.lambdaFieldAccessFilter(tree)) { + super.visitSelect(tree); + } else { + int prevPos = make.pos; + try { + make.at(tree); + + LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context; + JCTree ltree = lambdaContext.translate(tree); + if (ltree != null) { + result = ltree; + } else { + super.visitSelect(tree); + } + } finally { + make.at(prevPos); + } + } + } + @Override public void visitVarDef(JCVariableDecl tree) { LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context; @@ -1127,6 +1198,11 @@ public class LambdaToMethod extends TreeTranslator { */ private int lambdaCount = 0; + /** + * List of types undergoing construction via explicit constructor chaining. + */ + private List<ClassSymbol> typesUnderConstruction; + /** * keep the count of lambda expression defined in given context (used to * generate unambiguous names for serializable lambdas) @@ -1157,10 +1233,35 @@ public class LambdaToMethod extends TreeTranslator { private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) { frameStack = List.nil(); + typesUnderConstruction = List.nil(); localClassDefs = new HashMap<>(); return translate(tree); } + @Override + public void visitApply(JCMethodInvocation tree) { + List<ClassSymbol> previousNascentTypes = typesUnderConstruction; + try { + Name methName = TreeInfo.name(tree.meth); + if (methName == names._this || methName == names._super) { + typesUnderConstruction = typesUnderConstruction.prepend(currentClass()); + } + super.visitApply(tree); + } finally { + typesUnderConstruction = previousNascentTypes; + } + } + // where + private ClassSymbol currentClass() { + for (Frame frame : frameStack) { + if (frame.tree.hasTag(JCTree.Tag.CLASSDEF)) { + JCClassDecl cdef = (JCClassDecl) frame.tree; + return cdef.sym; + } + } + return null; + } + @Override public void visitBlock(JCBlock tree) { List<Frame> prevStack = frameStack; @@ -1632,6 +1733,22 @@ public class LambdaToMethod extends TreeTranslator { && sym.name != names.init; } + /** + * This is used to filter out those select nodes that need to be adjusted + * when translating away lambda expressions - at the moment, this is the + * set of nodes that select `this' (qualified this) + */ + private boolean lambdaFieldAccessFilter(JCFieldAccess fAccess) { + LambdaTranslationContext lambdaContext = + context instanceof LambdaTranslationContext ? + (LambdaTranslationContext) context : null; + return lambdaContext != null + && !fAccess.sym.isStatic() + && fAccess.name == names._this + && (fAccess.sym.owner.kind == TYP) + && !lambdaContext.translatedSymbols.get(CAPTURED_OUTER_THIS).isEmpty(); + } + /** * This is used to filter out those new class expressions that need to * be qualified with an enclosing tree @@ -1806,6 +1923,7 @@ public class LambdaToMethod extends TreeTranslator { translatedSymbols.put(LOCAL_VAR, new LinkedHashMap<Symbol, Symbol>()); translatedSymbols.put(CAPTURED_VAR, new LinkedHashMap<Symbol, Symbol>()); translatedSymbols.put(CAPTURED_THIS, new LinkedHashMap<Symbol, Symbol>()); + translatedSymbols.put(CAPTURED_OUTER_THIS, new LinkedHashMap<Symbol, Symbol>()); translatedSymbols.put(TYPE_VAR, new LinkedHashMap<Symbol, Symbol>()); freeVarProcessedLocalClasses = new HashSet<>(); @@ -1918,6 +2036,16 @@ public class LambdaToMethod extends TreeTranslator { } }; break; + case CAPTURED_OUTER_THIS: + Name name = names.fromString(new String(sym.flatName().toString() + names.dollarThis)); + ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, name, types.erasure(sym.type), translatedSym) { + @Override + public Symbol baseSymbol() { + //keep mapping with original captured symbol + return sym; + } + }; + break; case LOCAL_VAR: ret = new VarSymbol(sym.flags() & FINAL, sym.name, sym.type, translatedSym); ((VarSymbol) ret).pos = ((VarSymbol) sym).pos; @@ -1938,6 +2066,14 @@ public class LambdaToMethod extends TreeTranslator { } void addSymbol(Symbol sym, LambdaSymbolKind skind) { + if (skind == CAPTURED_THIS && sym != null && sym.kind == TYP && !typesUnderConstruction.isEmpty()) { + ClassSymbol currentClass = currentClass(); + if (currentClass != null && typesUnderConstruction.contains(currentClass)) { + // reference must be to enclosing outer instance, mutate capture kind. + Assert.check(sym != currentClass); // should have been caught right in Attr + skind = CAPTURED_OUTER_THIS; + } + } Map<Symbol, Symbol> transMap = getSymbolMap(skind); if (!transMap.containsKey(sym)) { transMap.put(sym, translate(sym, skind)); @@ -1951,17 +2087,49 @@ public class LambdaToMethod extends TreeTranslator { } JCTree translate(JCIdent lambdaIdent) { - for (Map<Symbol, Symbol> m : translatedSymbols.values()) { - if (m.containsKey(lambdaIdent.sym)) { - Symbol tSym = m.get(lambdaIdent.sym); - JCTree t = make.Ident(tSym).setType(lambdaIdent.type); - tSym.setTypeAttributes(lambdaIdent.sym.getRawTypeAttributes()); - return t; + for (LambdaSymbolKind kind : LambdaSymbolKind.values()) { + Map<Symbol, Symbol> m = getSymbolMap(kind); + switch(kind) { + default: + if (m.containsKey(lambdaIdent.sym)) { + Symbol tSym = m.get(lambdaIdent.sym); + JCTree t = make.Ident(tSym).setType(lambdaIdent.type); + tSym.setTypeAttributes(lambdaIdent.sym.getRawTypeAttributes()); + return t; + } + break; + case CAPTURED_OUTER_THIS: + if (lambdaIdent.sym.owner.kind == TYP && m.containsKey(lambdaIdent.sym.owner)) { + // Transform outer instance variable references anchoring them to the captured synthetic. + Symbol tSym = m.get(lambdaIdent.sym.owner); + JCExpression t = make.Ident(tSym).setType(lambdaIdent.sym.owner.type); + tSym.setTypeAttributes(lambdaIdent.sym.owner.getRawTypeAttributes()); + t = make.Select(t, lambdaIdent.name); + t.setType(lambdaIdent.type); + TreeInfo.setSymbol(t, lambdaIdent.sym); + return t; + } + break; } } return null; } + /* Translate away qualified this expressions, anchoring them to synthetic parameters that + capture the qualified this handle. `fieldAccess' is guaranteed to one such. + */ + public JCTree translate(JCFieldAccess fieldAccess) { + Assert.check(fieldAccess.name == names._this); + Map<Symbol, Symbol> m = translatedSymbols.get(LambdaSymbolKind.CAPTURED_OUTER_THIS); + if (m.containsKey(fieldAccess.sym.owner)) { + Symbol tSym = m.get(fieldAccess.sym.owner); + JCExpression t = make.Ident(tSym).setType(fieldAccess.sym.owner.type); + tSym.setTypeAttributes(fieldAccess.sym.owner.getRawTypeAttributes()); + return t; + } + return null; + } + /** * The translatedSym is not complete/accurate until the analysis is * finished. Once the analysis is finished, the translatedSym is @@ -1999,6 +2167,10 @@ public class LambdaToMethod extends TreeTranslator { params.append(make.VarDef((VarSymbol) thisSym, null)); parameterSymbols.append((VarSymbol) thisSym); } + for (Symbol thisSym : getSymbolMap(CAPTURED_OUTER_THIS).values()) { + params.append(make.VarDef((VarSymbol) thisSym, null)); + parameterSymbols.append((VarSymbol) thisSym); + } for (Symbol thisSym : getSymbolMap(PARAM).values()) { params.append(make.VarDef((VarSymbol) thisSym, null)); parameterSymbols.append((VarSymbol) thisSym); @@ -2096,9 +2268,6 @@ public class LambdaToMethod extends TreeTranslator { */ boolean interfaceParameterIsIntersectionType() { List<Type> tl = tree.getDescriptorType(types).getParameterTypes(); - if (tree.kind == ReferenceKind.UNBOUND) { - tl = tl.tail; - } for (; tl.nonEmpty(); tl = tl.tail) { Type pt = tl.head; if (pt.getKind() == TypeKind.TYPEVAR) { @@ -2147,6 +2316,7 @@ public class LambdaToMethod extends TreeTranslator { LOCAL_VAR, // original to translated lambda locals CAPTURED_VAR, // variables in enclosing scope to translated synthetic parameters CAPTURED_THIS, // class symbols to translated synthetic parameters (for captured member access) + CAPTURED_OUTER_THIS, // used when `this' capture is illegal, but outer this capture is legit (JDK-8129740) TYPE_VAR // original to translated lambda type variables } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index b5e3a8e5db98a8106e9e1001854d91a77a09cca4..423adf2e121b5e719e6dc83dc9406ebc02f8b3d7 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -1740,7 +1740,7 @@ public class Lower extends TreeTranslator { private JCStatement makeResourceCloseInvocation(JCExpression resource) { // convert to AutoCloseable if needed if (types.asSuper(resource.type, syms.autoCloseableType.tsym) == null) { - resource = (JCExpression) convert(resource, syms.autoCloseableType); + resource = convert(resource, syms.autoCloseableType); } // create resource.close() method invocation @@ -2179,7 +2179,7 @@ public class Lower extends TreeTranslator { *************************************************************************/ interface TreeBuilder { - JCTree build(JCTree arg); + JCExpression build(JCExpression arg); } /** Construct an expression using the builder, with the given rval @@ -2197,7 +2197,7 @@ public class Lower extends TreeTranslator { * where <code><b>TEMP</b></code> is a newly declared variable * in the let expression. */ - JCTree abstractRval(JCTree rval, Type type, TreeBuilder builder) { + JCExpression abstractRval(JCExpression rval, Type type, TreeBuilder builder) { rval = TreeInfo.skipParens(rval); switch (rval.getTag()) { case LITERAL: @@ -2215,15 +2215,15 @@ public class Lower extends TreeTranslator { type, currentMethodSym); rval = convert(rval,type); - JCVariableDecl def = make.VarDef(var, (JCExpression)rval); // XXX cast - JCTree built = builder.build(make.Ident(var)); - JCTree res = make.LetExpr(def, built); + JCVariableDecl def = make.VarDef(var, rval); // XXX cast + JCExpression built = builder.build(make.Ident(var)); + JCExpression res = make.LetExpr(def, built); res.type = built.type; return res; } // same as above, with the type of the temporary variable computed - JCTree abstractRval(JCTree rval, TreeBuilder builder) { + JCExpression abstractRval(JCExpression rval, TreeBuilder builder) { return abstractRval(rval, rval.type, builder); } @@ -2232,30 +2232,28 @@ public class Lower extends TreeTranslator { // Select expressions, where we place the left-hand-side of the // select in a temporary, and for Indexed expressions, where we // place both the indexed expression and the index value in temps. - JCTree abstractLval(JCTree lval, final TreeBuilder builder) { + JCExpression abstractLval(JCExpression lval, final TreeBuilder builder) { lval = TreeInfo.skipParens(lval); switch (lval.getTag()) { case IDENT: return builder.build(lval); case SELECT: { final JCFieldAccess s = (JCFieldAccess)lval; - JCTree selected = TreeInfo.skipParens(s.selected); Symbol lid = TreeInfo.symbol(s.selected); if (lid != null && lid.kind == TYP) return builder.build(lval); return abstractRval(s.selected, new TreeBuilder() { - public JCTree build(final JCTree selected) { - return builder.build(make.Select((JCExpression)selected, s.sym)); + public JCExpression build(final JCExpression selected) { + return builder.build(make.Select(selected, s.sym)); } }); } case INDEXED: { final JCArrayAccess i = (JCArrayAccess)lval; return abstractRval(i.indexed, new TreeBuilder() { - public JCTree build(final JCTree indexed) { + public JCExpression build(final JCExpression indexed) { return abstractRval(i.index, syms.intType, new TreeBuilder() { - public JCTree build(final JCTree index) { - JCTree newLval = make.Indexed((JCExpression)indexed, - (JCExpression)index); + public JCExpression build(final JCExpression index) { + JCExpression newLval = make.Indexed(indexed, index); newLval.setType(i.type); return builder.build(newLval); } @@ -2271,9 +2269,9 @@ public class Lower extends TreeTranslator { } // evaluate and discard the first expression, then evaluate the second. - JCTree makeComma(final JCTree expr1, final JCTree expr2) { + JCExpression makeComma(final JCExpression expr1, final JCExpression expr2) { return abstractRval(expr1, new TreeBuilder() { - public JCTree build(final JCTree discarded) { + public JCExpression build(final JCExpression discarded) { return expr2; } }); @@ -2306,7 +2304,7 @@ public class Lower extends TreeTranslator { /** Visitor method: Translate a single node, boxing or unboxing if needed. */ - public <T extends JCTree> T translate(T tree, Type type) { + public <T extends JCExpression> T translate(T tree, Type type) { return (tree == null) ? null : boxIfNeeded(translate(tree), type); } @@ -2332,7 +2330,7 @@ public class Lower extends TreeTranslator { /** Visitor method: Translate list of trees. */ - public <T extends JCTree> List<T> translate(List<T> trees, Type type) { + public <T extends JCExpression> List<T> translate(List<T> trees, Type type) { if (trees == null) return null; for (List<T> l = trees; l.nonEmpty(); l = l.tail) l.head = translate(l.head, type); @@ -2907,10 +2905,10 @@ public class Lower extends TreeTranslator { } } //where - private JCTree convert(JCTree tree, Type pt) { + private JCExpression convert(JCExpression tree, Type pt) { if (tree.type == pt || tree.type.hasTag(BOT)) return tree; - JCTree result = make_at(tree.pos()).TypeCast(make.Type(pt), (JCExpression)tree); + JCExpression result = make_at(tree.pos()).TypeCast(make.Type(pt), tree); result.type = (tree.type.constValue() != null) ? cfolder.coerce(tree.type, pt) : pt; return result; @@ -3075,7 +3073,7 @@ public class Lower extends TreeTranslator { /** Expand a boxing or unboxing conversion if needed. */ @SuppressWarnings("unchecked") // XXX unchecked - <T extends JCTree> T boxIfNeeded(T tree, Type type) { + <T extends JCExpression> T boxIfNeeded(T tree, Type type) { boolean havePrimitive = tree.type.isPrimitive(); if (havePrimitive == type.isPrimitive()) return tree; @@ -3084,12 +3082,12 @@ public class Lower extends TreeTranslator { if (!unboxedTarget.hasTag(NONE)) { if (!types.isSubtype(tree.type, unboxedTarget)) //e.g. Character c = 89; tree.type = unboxedTarget.constType(tree.type.constValue()); - return (T)boxPrimitive((JCExpression)tree, types.erasure(type)); + return (T)boxPrimitive(tree, types.erasure(type)); } else { - tree = (T)boxPrimitive((JCExpression)tree); + tree = (T)boxPrimitive(tree); } } else { - tree = (T)unbox((JCExpression)tree, type); + tree = (T)unbox(tree, type); } return tree; } @@ -3172,7 +3170,7 @@ public class Lower extends TreeTranslator { // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y) // (but without recomputing x) JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() { - public JCTree build(final JCTree lhs) { + public JCExpression build(final JCExpression lhs) { JCTree.Tag newTag = tree.getTag().noAssignOp(); // Erasure (TransTypes) can change the type of // tree.lhs. However, we can still get the @@ -3182,7 +3180,7 @@ public class Lower extends TreeTranslator { newTag, tree.type, tree.rhs.type); - JCExpression expr = (JCExpression)lhs; + JCExpression expr = lhs; if (expr.type != tree.type) expr = make.TypeCast(tree.type, expr); JCBinary opResult = make.Binary(newTag, expr, tree.rhs); @@ -3191,7 +3189,7 @@ public class Lower extends TreeTranslator { JCExpression newRhs = boxingReq ? make.TypeCast(types.unboxedType(tree.type), opResult) : opResult; - return make.Assign((JCExpression)lhs, newRhs).setType(tree.type); + return make.Assign(lhs, newRhs).setType(tree.type); } }); result = translate(newTree); @@ -3218,22 +3216,22 @@ public class Lower extends TreeTranslator { } /** Lower a tree of the form e++ or e-- where e is an object type */ - JCTree lowerBoxedPostop(final JCUnary tree) { + JCExpression lowerBoxedPostop(final JCUnary tree) { // translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2 // or // translate to tmp1=lval(e); tmp2=tmp1; (typeof tree)tmp1 OP 1; tmp2 // where OP is += or -= final boolean cast = TreeInfo.skipParens(tree.arg).hasTag(TYPECAST); return abstractLval(tree.arg, new TreeBuilder() { - public JCTree build(final JCTree tmp1) { + public JCExpression build(final JCExpression tmp1) { return abstractRval(tmp1, tree.arg.type, new TreeBuilder() { - public JCTree build(final JCTree tmp2) { + public JCExpression build(final JCExpression tmp2) { JCTree.Tag opcode = (tree.hasTag(POSTINC)) ? PLUS_ASG : MINUS_ASG; JCTree lhs = cast - ? make.TypeCast(tree.arg.type, (JCExpression)tmp1) + ? make.TypeCast(tree.arg.type, tmp1) : tmp1; - JCTree update = makeAssignop(opcode, + JCExpression update = makeAssignop(opcode, lhs, make.Literal(1)); return makeComma(update, tmp2); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java index 7e174217cf4b557f2e8beccf075098e9009a2eb8..9f2ff731f2ec95a09828b4fe345ee17fbeb9b73e 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -32,6 +32,7 @@ import com.sun.tools.javac.code.Attribute.TypeCompound; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; @@ -834,10 +835,6 @@ public class TransTypes extends TreeTranslator { public void visitSelect(JCFieldAccess tree) { Type t = types.skipTypeVars(tree.selected.type, false); if (t.isCompound()) { - if ((tree.sym.flags() & IPROXY) != 0) { - tree.sym = ((MethodSymbol)tree.sym). - implemented((TypeSymbol)tree.sym.owner, types); - } tree.selected = coerce( translate(tree.selected, erasure(tree.selected.type)), erasure(tree.sym.owner.type)); @@ -859,7 +856,14 @@ public class TransTypes extends TreeTranslator { } public void visitReference(JCMemberReference tree) { - tree.expr = translate(tree.expr, erasure(tree.expr.type)); + Type t = types.skipTypeVars(tree.expr.type, false); + Type receiverTarget = t.isCompound() ? erasure(tree.sym.owner.type) : erasure(t); + if (tree.kind == ReferenceKind.UNBOUND) { + tree.expr = make.Type(receiverTarget); + } else { + tree.expr = translate(tree.expr, receiverTarget); + } + tree.type = erasure(tree.type); if (tree.varargsElement != null) tree.varargsElement = erasure(tree.varargsElement); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 10db4ef33ac2b539c911dd5de891df675deec126..81dd6225b0700404676135a3a2208d579b54ec8d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1112,7 +1112,8 @@ public class ClassWriter extends ClassFile { acount += writeMethodParametersAttr(m); } acount += writeMemberAttrs(m); - acount += writeParameterAttrs(m); + if (!m.isLambdaMethod()) + acount += writeParameterAttrs(m); endAttrs(acountIdx, acount); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 5151729a66886b0719134723b7ba5fa9f6915fe3..f2aa73437bd397dcbbcc3baa3184aa69df7af64a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -2283,6 +2283,10 @@ compiler.warn.override.equals.but.not.hashcode=\ compiler.misc.cant.override=\ {0} in {1} cannot override {2} in {3} +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.misc.cant.hide=\ + {0} in {1} cannot hide {2} in {3} + # 0: symbol, 1: symbol, 2: symbol, 3: symbol compiler.misc.cant.implement=\ {0} in {1} cannot implement {2} in {3} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java index b93f51a47c7ff2e4e8008d04a303655789aec18f..3016af5189e91e4231909a2b5ed25ab47c011af2 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -2623,8 +2623,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** (let int x = 3; in x+2) */ public static class LetExpr extends JCExpression { public List<JCVariableDecl> defs; - public JCTree expr; - protected LetExpr(List<JCVariableDecl> defs, JCTree expr) { + public JCExpression expr; + protected LetExpr(List<JCVariableDecl> defs, JCExpression expr) { this.defs = defs; this.expr = expr; } @@ -2731,7 +2731,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args); JCModifiers Modifiers(long flags, List<JCAnnotation> annotations); JCErroneous Erroneous(List<? extends JCTree> errs); - LetExpr LetExpr(List<JCVariableDecl> defs, JCTree expr); + LetExpr LetExpr(List<JCVariableDecl> defs, JCExpression expr); } /** A generic visitor class for trees. diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java index 9fc7aa381e7950c008d358f4fbe268e36c8566a3..e36cbaae9c2787ddf49af4d1fb93d2922ffa92fb 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -512,7 +512,7 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> { case LETEXPR: { LetExpr t = (LetExpr) node; List<JCVariableDecl> defs = copy(t.defs, p); - JCTree expr = copy(t.expr, p); + JCExpression expr = copy(t.expr, p); return M.at(t.pos).LetExpr(defs, expr); } default: diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 1bd0ac6d72384def366c961ee916f0108f39e30b..959d81258ec06960cd04467d3390ef595fd4e2b7 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -552,7 +552,7 @@ public class TreeMaker implements JCTree.Factory { return tree; } - public LetExpr LetExpr(List<JCVariableDecl> defs, JCTree expr) { + public LetExpr LetExpr(List<JCVariableDecl> defs, JCExpression expr) { LetExpr tree = new LetExpr(defs, expr); tree.pos = pos; return tree; @@ -573,7 +573,7 @@ public class TreeMaker implements JCTree.Factory { defs); } - public LetExpr LetExpr(JCVariableDecl def, JCTree expr) { + public LetExpr LetExpr(JCVariableDecl def, JCExpression expr) { LetExpr tree = new LetExpr(List.of(def), expr); tree.pos = pos; return tree; @@ -628,6 +628,12 @@ public class TreeMaker implements JCTree.Factory { return Ident(new VarSymbol(FINAL, names._this, t, t.tsym)); } + /** Create a tree representing qualified `this' given its type + */ + public JCExpression QualThis(Type t) { + return Select(Type(t), new VarSymbol(FINAL, names._this, t, t.tsym)); + } + /** Create a tree representing a class literal. */ public JCExpression ClassLiteral(ClassSymbol clazz) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java index aec703c91b2eb4e2537072ff1ec5918f022ad6d1..4f5b11f07a5f10a8cce0ef4d4a6ab9e00a806c92 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java @@ -177,6 +177,7 @@ public class Names { public final Name lambda; public final Name metafactory; public final Name altMetafactory; + public final Name dollarThis; public final Name.Table table; @@ -235,6 +236,7 @@ public class Names { value = fromString("value"); valueOf = fromString("valueOf"); values = fromString("values"); + dollarThis = fromString("$this"); // class names java_io_Serializable = fromString("java.io.Serializable"); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 9bc5567cda4ad05aadede10e0694a77a8eb0b66d..cc4124d52763ac74d52ad4eb4580d51213cfd057 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -675,6 +675,9 @@ public class JShellTool { registerCommand(new Command("/classes", "/c", null, "list the declared classes", arg -> cmdClasses(), EMPTY_COMPLETION_PROVIDER)); + registerCommand(new Command("/imports", "/i", null, "list the imported items", + arg -> cmdImports(), + EMPTY_COMPLETION_PROVIDER)); registerCommand(new Command("/exit", "/x", null, "exit the REPL", arg -> cmdExit(), EMPTY_COMPLETION_PROVIDER)); @@ -1256,6 +1259,12 @@ public class JShellTool { } } + private void cmdImports() { + state.imports().forEach(ik -> { + hard(" import %s%s", ik.isStatic() ? "static " : "", ik.fullname()); + }); + } + private void cmdUseHistoryEntry(int index) { List<Snippet> keys = state.snippets(); if (index < 0) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java index c3620de04305579bbcd1f129ce9cb47ef0a7c257..c598442a387a76200310f3b3164706c15ecefb04 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java @@ -68,6 +68,29 @@ public class ImportSnippet extends PersistentSnippet { return key().name(); } + /** + * + * The qualified name of the import. For any imports + * ({@link jdk.jshell.Snippet.SubKind#TYPE_IMPORT_ON_DEMAND_SUBKIND}, + * ({@link jdk.jshell.Snippet.SubKind#STATIC_IMPORT_ON_DEMAND_SUBKIND}), + * ({@link jdk.jshell.Snippet.SubKind#SINGLE_TYPE_IMPORT_SUBKIND} or + * ({@link jdk.jshell.Snippet.SubKind#SINGLE_STATIC_IMPORT_SUBKIND}) + * that is the full specifier including any + * qualifiers and the asterisks. + * @return the fullname of the import + */ + public String fullname() { + return fullname; + } + + /** + * When this snippet represent static import, this method returns true. + * @return true when this snippet represent static import, otherwise false + */ + public boolean isStatic() { + return isStatic; + } + /**** internal access ****/ @Override @@ -75,10 +98,6 @@ public class ImportSnippet extends PersistentSnippet { return (ImportKey) super.key(); } - boolean isStatic() { - return isStatic; - } - @Override String importLine(JShell state) { return source(); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java index 7616da7ccff50454184b014b24097b2f11ffed67..858aee274dd716da6279e9e489fe22ca21737238 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java @@ -93,7 +93,7 @@ public class JShell implements AutoCloseable { private ExecutionControl executionControl = null; - private SourceCodeAnalysis sourceCodeAnalysis = null; + private SourceCodeAnalysisImpl sourceCodeAnalysis = null; JShell(Builder b) { @@ -378,6 +378,9 @@ public class JShell implements AutoCloseable { public void addToClasspath(String path) { taskFactory.addToClasspath(path); // Compiler executionControl().commandAddToClasspath(path); // Runtime + if (sourceCodeAnalysis != null) { + sourceCodeAnalysis.classpathChanged(); + } } /** @@ -468,6 +471,22 @@ public class JShell implements AutoCloseable { .collect(collectingAndThen(toList(), Collections::unmodifiableList)); } + /** + * Returns the active import snippets. + * This convenience method is equivalent to <code>snippets()</code> filtered for + * {@link jdk.jshell.Snippet.Status#isActive status(snippet).isActive} + * <code>&& snippet.kind() == Kind.IMPORT</code> + * and cast to ImportSnippet. + * @return the active declared import declarations. + * @throws IllegalStateException if this JShell instance is closed. + */ + public List<ImportSnippet> imports() throws IllegalStateException { + return snippets().stream() + .filter(sn -> status(sn).isActive && sn.kind() == Snippet.Kind.IMPORT) + .map(sn -> (ImportSnippet) sn) + .collect(collectingAndThen(toList(), Collections::unmodifiableList)); + } + /** * Return the status of the snippet. * This is updated either because of an explicit <code>eval()</code> call or diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java index 5fdf1b7748aa3dd32f1de01fa5858bfc243b0f59..ed79e4f3845374c6131315a06877a895ff445714 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java @@ -42,6 +42,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.TreeMap; + import javax.tools.JavaFileObject.Kind; import static javax.tools.StandardLocation.CLASS_PATH; import javax.tools.FileObject; @@ -49,6 +50,7 @@ import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; @@ -77,6 +79,10 @@ class MemoryFileManager implements JavaFileManager { private Method inferModuleNameMethod = null; private Method listModuleLocationsMethod = null; + Iterable<? extends Path> getLocationAsPaths(Location loc) { + return this.stdFileManager.getLocationAsPaths(loc); + } + static abstract class MemoryJavaFileObject extends SimpleJavaFileObject { public MemoryJavaFileObject(String name, JavaFileObject.Kind kind) { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index b55b23585f3d5b9354c189e6226664dbef2f7dca..d3bb4803e8ea25b5f8ae27e37079d9c345e8b456 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -75,8 +75,14 @@ import javax.lang.model.type.TypeMirror; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_COMPA; import java.io.IOException; +import java.net.URI; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Comparator; -import java.util.EnumSet; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.Set; @@ -92,6 +98,7 @@ import static java.util.stream.Collectors.toSet; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import javax.lang.model.SourceVersion; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.QualifiedNameable; @@ -100,10 +107,8 @@ import javax.lang.model.type.ArrayType; import javax.lang.model.type.ExecutableType; import javax.lang.model.type.TypeKind; import javax.lang.model.util.ElementFilter; -import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.JavaFileManager.Location; -import javax.tools.JavaFileObject; import javax.tools.StandardLocation; import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; @@ -584,42 +589,114 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { .collect(toList()); } + private Set<String> emptyContextPackages = null; + + void classpathChanged() { + emptyContextPackages = null; + } + private Set<PackageElement> listPackages(AnalyzeTask at, String enclosingPackage) { - Set<PackageElement> packs = new HashSet<>(); - listPackages(at, StandardLocation.PLATFORM_CLASS_PATH, enclosingPackage, packs); - listPackages(at, StandardLocation.CLASS_PATH, enclosingPackage, packs); - listPackages(at, StandardLocation.SOURCE_PATH, enclosingPackage, packs); - return packs; + Set<String> packs; + + if (enclosingPackage.isEmpty() && emptyContextPackages != null) { + packs = emptyContextPackages; + } else { + packs = new HashSet<>(); + + listPackages(StandardLocation.PLATFORM_CLASS_PATH, enclosingPackage, packs); + listPackages(StandardLocation.CLASS_PATH, enclosingPackage, packs); + listPackages(StandardLocation.SOURCE_PATH, enclosingPackage, packs); + + if (enclosingPackage.isEmpty()) { + emptyContextPackages = packs; + } + } + + return packs.stream() + .map(pkg -> createPackageElement(at, pkg)) + .collect(Collectors.toSet()); } - private void listPackages(AnalyzeTask at, Location loc, String currentPackage, Set<PackageElement> packs) { + private PackageElement createPackageElement(AnalyzeTask at, String packageName) { + Names names = Names.instance(at.getContext()); + Symtab syms = Symtab.instance(at.getContext()); + PackageElement existing = syms.enterPackage(names.fromString(packageName)); + + return existing; + } + + private void listPackages(Location loc, String enclosing, Set<String> packs) { + Iterable<? extends Path> paths = proc.taskFactory.fileManager().getLocationAsPaths(loc); + + if (paths == null) + return ; + + for (Path p : paths) { + listPackages(p, enclosing, packs); + } + } + + private void listPackages(Path path, String enclosing, Set<String> packages) { try { - MemoryFileManager fm = proc.taskFactory.fileManager(); - for (JavaFileObject file : fm.list(loc, currentPackage, fileKinds, true)) { - String binaryName = fm.inferBinaryName(loc, file); - if (!currentPackage.isEmpty() && !binaryName.startsWith(currentPackage + ".")) - continue; - int nextDot = binaryName.indexOf('.', !currentPackage.isEmpty() ? currentPackage.length() + 1 : 0); - if (nextDot == (-1)) - continue; - Elements elements = at.getElements(); - PackageElement pack = - elements.getPackageElement(binaryName.substring(0, nextDot)); - if (pack == null) { - //if no types in the package have ever been seen, the package will be unknown - //try to load a type, and then try to recognize the package again: - elements.getTypeElement(binaryName); - pack = elements.getPackageElement(binaryName.substring(0, nextDot)); + if (path.equals(Paths.get("JRT_MARKER_FILE"))) { + FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/")); + Path modules = jrtfs.getPath("modules"); + try (DirectoryStream<Path> stream = Files.newDirectoryStream(modules)) { + for (Path c : stream) { + listDirectory(c, enclosing, packages); + } } - if (pack != null) - packs.add(pack); + } else if (!Files.isDirectory(path)) { + if (Files.exists(path)) { + ClassLoader cl = SourceCodeAnalysisImpl.class.getClassLoader(); + + try (FileSystem zip = FileSystems.newFileSystem(path, cl)) { + listDirectory(zip.getRootDirectories().iterator().next(), enclosing, packages); + } + } + } else { + listDirectory(path, enclosing, packages); } } catch (IOException ex) { - //TODO: should log? + proc.debug(ex, "SourceCodeAnalysisImpl.listPackages(" + path.toString() + ", " + enclosing + ", " + packages + ")"); } } - //where: - private final Set<JavaFileObject.Kind> fileKinds = EnumSet.of(JavaFileObject.Kind.CLASS); + + private void listDirectory(Path path, String enclosing, Set<String> packages) throws IOException { + String separator = path.getFileSystem().getSeparator(); + Path resolved = path.resolve(enclosing.replace(".", separator)); + + if (Files.isDirectory(resolved)) { + try (DirectoryStream<Path> ds = Files.newDirectoryStream(resolved)) { + for (Path entry : ds) { + String name = pathName(entry); + + if (SourceVersion.isIdentifier(name) && + Files.isDirectory(entry) && + validPackageCandidate(entry)) { + packages.add(enclosing + (enclosing.isEmpty() ? "" : ".") + name); + } + } + } + } + } + + private boolean validPackageCandidate(Path p) throws IOException { + try (Stream<Path> dir = Files.list(p)) { + return dir.anyMatch(e -> Files.isDirectory(e) && SourceVersion.isIdentifier(pathName(e)) || + e.getFileName().toString().endsWith(".class")); + } + } + + private String pathName(Path p) { + String separator = p.getFileSystem().getSeparator(); + String name = p.getFileName().toString(); + + if (name.endsWith(separator)) //jars have '/' appended + name = name.substring(0, name.length() - separator.length()); + + return name; + } private Element createArrayLengthSymbol(AnalyzeTask at, TypeMirror site) { Name length = Names.instance(at.getContext()).length; diff --git a/langtools/test/jdk/jshell/CompletionSuggestionTest.java b/langtools/test/jdk/jshell/CompletionSuggestionTest.java index 1f27d0c43eb8b8136c588232e420453b26378c93..5ff91c5929d129dc7b7a1dd29d5b2103eed6c551 100644 --- a/langtools/test/jdk/jshell/CompletionSuggestionTest.java +++ b/langtools/test/jdk/jshell/CompletionSuggestionTest.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8141092 * @summary Test Completion * @library /tools/lib * @build KullaTesting TestingInputStream ToolBox Compiler @@ -45,6 +46,9 @@ import static jdk.jshell.Snippet.Status.OVERWRITTEN; @Test public class CompletionSuggestionTest extends KullaTesting { + private final Compiler compiler = new Compiler(); + private final Path outDir = Paths.get("completion_suggestion_test"); + public void testMemberExpr() { assertEval("class Test { static void test() { } }"); assertCompletion("Test.t|", "test()"); @@ -232,6 +236,23 @@ public class CompletionSuggestionTest extends KullaTesting { assertCompletion("Object.notElement.|"); assertCompletion("Object o = com.su|", "sun"); + + Path p1 = outDir.resolve("dir1"); + compiler.compile(p1, + "package p1.p2;\n" + + "public class Test {\n" + + "}", + "package p1.p3;\n" + + "public class Test {\n" + + "}"); + String jarName = "test.jar"; + compiler.jar(p1, jarName, "p1/p2/Test.class", "p1/p3/Test.class"); + addToClasspath(compiler.getPath(p1.resolve(jarName))); + + assertCompletionIncludesExcludes("|", new HashSet<>(Collections.singletonList("p1")), Collections.emptySet()); + assertCompletion("p1.|", "p2", "p3"); + assertCompletion("p1.p2.|", "Test"); + assertCompletion("p1.p3.|", "Test"); } public void testCheckAccessibility() { diff --git a/langtools/test/jdk/jshell/ReplToolTesting.java b/langtools/test/jdk/jshell/ReplToolTesting.java index cd07af1f92847ef4d61a3e1b15fb0d47c1c90ba0..88bac9102d9cfdf392ee3c528cdc997d68490597 100644 --- a/langtools/test/jdk/jshell/ReplToolTesting.java +++ b/langtools/test/jdk/jshell/ReplToolTesting.java @@ -27,11 +27,10 @@ import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -62,6 +61,7 @@ public class ReplToolTesting { private Map<String, VariableInfo> variables; private Map<String, MethodInfo> methods; private Map<String, ClassInfo> classes; + private Map<String, ImportInfo> imports; private boolean isDefaultStartUp = true; public JShellTool repl = null; @@ -127,6 +127,10 @@ public class ReplToolTesting { return assertMembers("Classes", classes); } + public Consumer<String> assertImports() { + return assertMembers("Imports", imports); + } + public String getCommandOutput() { String s = cmdout.toString(); cmdout.reset(); @@ -184,9 +188,21 @@ public class ReplToolTesting { variables = new HashMap<>(); methods = new HashMap<>(); classes = new HashMap<>(); + imports = new HashMap<>(); if (isDefaultStartUp) { methods.put("printf (String,Object...)void", new MethodInfo("", "(String,Object...)void", "printf")); + imports.putAll( + Stream.of( + "java.util.*", + "java.io.*", + "java.math.*", + "java.net.*", + "java.util.concurrent.*", + "java.util.prefs.*", + "java.util.regex.*") + .map(s -> new ImportInfo("", "", s)) + .collect(Collectors.toMap(Object::toString, Function.identity()))); } } @@ -300,6 +316,19 @@ public class ReplToolTesting { addKey(after, clazz); } + public void loadImport(boolean after, String src, String type, String name) { + ImportInfo i = new ImportInfo(src, type, name); + addKey(after, i, imports); + addKey(after, i); + } + + public void assertImport(boolean after, String src, String type, String name) { + ImportInfo i = new ImportInfo(src, type, name); + assertCommandCheckOutput(after, src, i.checkOutput()); + addKey(after, i, imports); + addKey(after, i); + } + private <T extends MemberInfo> void addKey(boolean after, T memberInfo, Map<String, T> map) { if (after) { map.entrySet().removeIf(e -> e.getValue().equals(memberInfo)); @@ -347,6 +376,10 @@ public class ReplToolTesting { dropKey(after, cmd, name, classes); } + public void dropImport(boolean after, String cmd, String name) { + dropKey(after, cmd, name, imports); + } + public void assertCommand(boolean after, String cmd, String out) { assertCommand(after, cmd, out, "", null, "", ""); } @@ -580,6 +613,31 @@ public class ReplToolTesting { } } + public static class ImportInfo extends MemberInfo { + public ImportInfo(String source, String type, String fullname) { + super(source, type, fullname); + } + + @Override + public Consumer<String> checkOutput() { + return s -> assertTrue("".equals(s), "Expected: '', actual: " + s); + } + + @Override + public boolean equals(Object o) { + if (o instanceof ImportInfo) { + ImportInfo i = (ImportInfo) o; + return name.equals(i.name) && type.equals(i.type); + } + return false; + } + + @Override + public String toString() { + return String.format("import %s%s", type.equals("static") ? "static " : "", name); + } + } + class WaitingTestingInputStream extends TestingInputStream { @Override diff --git a/langtools/test/jdk/jshell/ToolBasicTest.java b/langtools/test/jdk/jshell/ToolBasicTest.java index d9137cec2bf6a3952d2b075a47c7ba22e6c008c7..7fba300dc0f8555c9b17e9de96eef14ffe16c936 100644 --- a/langtools/test/jdk/jshell/ToolBasicTest.java +++ b/langtools/test/jdk/jshell/ToolBasicTest.java @@ -24,7 +24,6 @@ /* * @test * @summary Tests for Basic tests for REPL tool - * @ignore 8139873 * @library /tools/lib * @build KullaTesting TestingInputStream ToolBox Compiler * @run testng ToolBasicTest @@ -139,7 +138,13 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertCommand(a, "class A {}\u0003", ""), (a) -> assertCommandCheckOutput(a, "/c", assertClasses()), (a) -> assertClass(a, "interface A {}", "interface", "A"), - (a) -> assertCommandCheckOutput(a, "/c", assertClasses()) + (a) -> assertCommandCheckOutput(a, "/c", assertClasses()), + (a) -> assertCommand(a, "import java.util.stream." + s, ""), + interrupt, + (a) -> assertCommand(a, "import java.util.stream.\u0003", ""), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()), + (a) -> assertImport(a, "import java.util.stream.Stream", "", "java.util.stream.Stream"), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()) ); } } @@ -364,6 +369,35 @@ public class ToolBasicTest extends ReplToolTesting { ); } + public void defineImports() { + test( + (a) -> assertCommandCheckOutput(a, "/l", assertList()), + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()), + (a) -> assertCommandCheckOutput(a, "/imports", assertImports()), + (a) -> assertImport(a, "import java.util.stream.Stream;", "", "java.util.stream.Stream"), + (a) -> assertCommandCheckOutput(a, "/l", assertList()), + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()), + (a) -> assertCommandCheckOutput(a, "/imports", assertImports()), + (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), + (a) -> assertCommandCheckOutput(a, "/l", assertList()), + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()), + (a) -> assertCommandCheckOutput(a, "/imports", assertImports()), + (a) -> assertImport(a, "import static java.lang.Math.PI;", "static", "java.lang.Math.PI"), + (a) -> assertCommandCheckOutput(a, "/l", assertList()), + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()), + (a) -> assertCommandCheckOutput(a, "/imports", assertImports()), + (a) -> assertImport(a, "import static java.lang.Math.*;", "static", "java.lang.Math.*"), + (a) -> assertCommandCheckOutput(a, "/l", assertList()), + (a) -> assertCommandCheckOutput(a, "/list", assertList()), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()), + (a) -> assertCommandCheckOutput(a, "/imports", assertImports()) + ); + } + public void testClasspathDirectory() { Compiler compiler = new Compiler(); Path outDir = Paths.get("testClasspathDirectory"); @@ -443,10 +477,13 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertCommandCheckOutput(a, "/m", assertMethods()), (a) -> assertClass(a, "class A { }", "class", "A"), (a) -> assertCommandCheckOutput(a, "/c", assertClasses()), + (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()), (a) -> assertReset(a, "/reset"), (a) -> assertCommandCheckOutput(a, "/v", assertVariables()), (a) -> assertCommandCheckOutput(a, "/m", assertMethods()), - (a) -> assertCommandCheckOutput(a, "/c", assertClasses()) + (a) -> assertCommandCheckOutput(a, "/c", assertClasses()), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()) ); } @@ -455,22 +492,26 @@ public class ToolBasicTest extends ReplToolTesting { Path path = compiler.getPath("testOpen.repl"); compiler.writeToFile(path, "int a = 10;\ndouble x = 20;\ndouble a = 10;\n" + - "class A { public String toString() { return \"A\"; } }"); + "class A { public String toString() { return \"A\"; } }\nimport java.util.stream.*;"); for (String s : new String[]{"/o", "/open"}) { test( (a) -> assertCommand(a, s + " " + path.toString(), ""), (a) -> assertCommand(a, "a", "| Variable a of type double has value 10.0\n"), (a) -> evaluateExpression(a, "A", "new A();", "\"A\""), + (a) -> evaluateExpression(a, "long", "Stream.of(\"A\").count();", "1"), (a) -> { loadVariable(a, "double", "x", "20.0", "20.0"); loadVariable(a, "double", "a", "10.0", "10.0"); - loadVariable(a, "A", "$6", "new A();", "A"); + loadVariable(a, "A", "$7", "new A();", "A"); + loadVariable(a, "long", "$8", "Stream.of(\"A\").count();", "1"); loadClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"); + loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*"); assertCommandCheckOutput(a, "/c", assertClasses()); }, (a) -> assertCommandCheckOutput(a, "/m", assertMethods()), - (a) -> assertCommandCheckOutput(a, "/v", assertVariables()) + (a) -> assertCommandCheckOutput(a, "/v", assertVariables()), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()) ); Path unknown = compiler.getPath("UNKNOWN.repl"); test( @@ -536,6 +577,7 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertVariable(a, "int", "a"), (a) -> assertVariable(a, "double", "b", "10", "10.0"), (a) -> assertMethod(a, "void f() {}", "()V", "f"), + (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertCommand(a, "/s " + startUpFile.toString(), null), (a) -> assertCommand(a, "/setstart " + startUpFile.toString(), null) ); @@ -549,10 +591,12 @@ public class ToolBasicTest extends ReplToolTesting { loadVariable(a, "int", "a"); loadVariable(a, "double", "b", "10.0", "10.0"); loadMethod(a, "void f() {}", "()void", "f"); + loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*"); assertCommandCheckOutput(a, "/c", assertClasses()); }, (a) -> assertCommandCheckOutput(a, "/v", assertVariables()), - (a) -> assertCommandCheckOutput(a, "/m", assertMethods()) + (a) -> assertCommandCheckOutput(a, "/m", assertMethods()), + (a) -> assertCommandCheckOutput(a, "/i", assertImports()) ); } finally { removeStartup(); @@ -768,9 +812,12 @@ public class ToolBasicTest extends ReplToolTesting { a -> dropMethod(a, drop + " 2", "b ()I"), a -> assertClass(a, "class A {}", "class", "A"), a -> dropClass(a, drop + " 3", "class A"), + a -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), + a -> dropImport(a, drop + " 4", "import java.util.stream.*"), a -> assertCommandCheckOutput(a, "/v", assertVariables()), a -> assertCommandCheckOutput(a, "/m", assertMethods()), - a -> assertCommandCheckOutput(a, "/c", assertClasses()) + a -> assertCommandCheckOutput(a, "/c", assertClasses()), + a -> assertCommandCheckOutput(a, "/i", assertImports()) ); test(false, new String[]{"-nostartup"}, a -> assertVariable(a, "int", "a"), @@ -781,7 +828,8 @@ public class ToolBasicTest extends ReplToolTesting { a -> dropClass(a, drop + " A", "class A"), a -> assertCommandCheckOutput(a, "/v", assertVariables()), a -> assertCommandCheckOutput(a, "/m", assertMethods()), - a -> assertCommandCheckOutput(a, "/c", assertClasses()) + a -> assertCommandCheckOutput(a, "/c", assertClasses()), + a -> assertCommandCheckOutput(a, "/i", assertImports()) ); } } @@ -814,7 +862,8 @@ public class ToolBasicTest extends ReplToolTesting { a -> assertCommandCheckOutput(a, drop + " a", check), a -> assertCommandCheckOutput(a, "/v", assertVariables()), a -> assertCommandCheckOutput(a, "/m", assertMethods()), - a -> assertCommandCheckOutput(a, "/c", assertClasses()) + a -> assertCommandCheckOutput(a, "/c", assertClasses()), + a -> assertCommandCheckOutput(a, "/i", assertImports()) ); test( a -> assertMethod(a, "int a() { return 0; }", "()int", "a"), diff --git a/langtools/test/tools/javac/OverrideChecks/T4720359a.out b/langtools/test/tools/javac/OverrideChecks/T4720359a.out index 54635de3a1fa36d1d4e897c92c988a0d2ddaa3fc..4f9ebc75892e83bf2bc59efe0b74cc7c65ecde11 100644 --- a/langtools/test/tools/javac/OverrideChecks/T4720359a.out +++ b/langtools/test/tools/javac/OverrideChecks/T4720359a.out @@ -1,2 +1,2 @@ -T4720359a.java:16:23: compiler.err.override.incompatible.ret: (compiler.misc.cant.override: m(), p1.T4720359c, m(), p1.T4720359a), int, void +T4720359a.java:16:23: compiler.err.override.incompatible.ret: (compiler.misc.cant.hide: m(), p1.T4720359c, m(), p1.T4720359a), int, void 1 error diff --git a/langtools/test/tools/javac/OverrideChecks/T8139255.java b/langtools/test/tools/javac/OverrideChecks/T8139255.java new file mode 100644 index 0000000000000000000000000000000000000000..dcb3e7e4601b5e5e3523c68b2603ca55d00a1fcf --- /dev/null +++ b/langtools/test/tools/javac/OverrideChecks/T8139255.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8139255 + * @summary javac emits diagnostic message as overriding instead of hiding for class methods. + * @compile/fail/ref=T8139255.out -XDrawDiagnostics T8139255.java + */ + +public class T8139255 { + static void func() { } +} + +class T8139255_1 extends T8139255 { + static int func() { return 0; } +} diff --git a/langtools/test/tools/javac/OverrideChecks/T8139255.out b/langtools/test/tools/javac/OverrideChecks/T8139255.out new file mode 100644 index 0000000000000000000000000000000000000000..be228593d73f4865c29264c309a37fad24a736ed --- /dev/null +++ b/langtools/test/tools/javac/OverrideChecks/T8139255.out @@ -0,0 +1,2 @@ +T8139255.java:13:15: compiler.err.override.incompatible.ret: (compiler.misc.cant.hide: func(), T8139255_1, func(), T8139255), int, void +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/InstanceInitializer.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/InstanceInitializer.java new file mode 100644 index 0000000000000000000000000000000000000000..732138e4cfc0571bdf620624eeae1981b435073e --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/InstanceInitializer.java @@ -0,0 +1,73 @@ +/* + * 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.util.ArrayList; + +import com.sun.tools.classfile.*; + +/* + * @test + * @bug 8136419 + * @summary test that type annotations on entities in initializers are emitted to classfile + * @modules jdk.jdeps/com.sun.tools.classfile + */ + +public class InstanceInitializer extends ClassfileTestHelper { + public static void main(String[] args) throws Exception { + new InstanceInitializer().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 4; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("InstanceInitializer$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m, true); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface T {} + + { + @T String s = null; + Runnable r = () -> new ArrayList<@T String>(); + } + @T String s = null; + Runnable r = () -> new ArrayList<@T String>(); + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/StaticInitializer.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/StaticInitializer.java new file mode 100644 index 0000000000000000000000000000000000000000..f75a3ab61b108c58d73a372dd247d1e781d419ee --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/StaticInitializer.java @@ -0,0 +1,73 @@ +/* + * 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.util.ArrayList; + +import com.sun.tools.classfile.*; + +/* + * @test + * @bug 8136419 + * @summary test that type annotations on entities in static initializers are emitted to classfile + * @modules jdk.jdeps/com.sun.tools.classfile + */ + +public class StaticInitializer extends ClassfileTestHelper { + public static void main(String[] args) throws Exception { + new StaticInitializer().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 4; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("StaticInitializer$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m, true); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface T {} + + static { + @T String s = null; + Runnable r = () -> new ArrayList<@T String>(); + } + @T static String s = null; + static Runnable r = () -> new ArrayList<@T String>(); + } +} diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java index 3aae43303320115decc79defc77558b2995a37e0..2887caf303eaeb1ce4791a2b143a8b1a86607fc1 100644 --- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java +++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java @@ -23,10 +23,9 @@ /* * @test - * @bug 8044411 8079060 + * @bug 8044411 8079060 8138612 * @summary Tests the RuntimeParameterVisibleAnnotations/RuntimeParameterInvisibleAnnotations attribute. * @library /tools/lib /tools/javac/lib ../lib - * @ignore 8079060 javac does not generate RuntimeParameterAnnotation attributes for lambda expressions * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox * @build TestCase ClassType TestAnnotationInfo * @build RuntimeParameterAnnotationsForLambdaTest AnnotationsTestBase RuntimeParameterAnnotationsTestBase @@ -36,12 +35,11 @@ import java.util.List; import java.util.stream.Collectors; -import com.sun.tools.classfile.ClassFile; -import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.*; /** * RuntimeParameterAnnotationsForLambdaTest is a test which checks that RuntimeVisibleParameterAnnotationsAttribute - * and RuntimeInvisibleParameterAnnotationsAttribute are generated properly for lambda expressions. + * and RuntimeInvisibleParameterAnnotationsAttribute are not generated at all for lambda expressions. * The test checks both single and repeatable annotations. * All possible combinations of retention policies are tested. * @@ -74,8 +72,8 @@ public class RuntimeParameterAnnotationsForLambdaTest extends RuntimeParameterAn TestCase.TestParameterInfo p3 = testMethodInfo.addParameter("String", "c"); annotations.annotate(p3); String source = SOURCE_TEMPLATE.replace("%SOURCE%", generateLambdaSource(testMethodInfo)); - echo("Testing:\n" + source); addTestCase(source); + echo("Testing:\n" + source); ClassFile classFile = readClassFile(compile(source).getClasses().get(CLASS_NAME)); boolean isFoundLambda = false; for (Method method : classFile.methods) { @@ -94,6 +92,17 @@ public class RuntimeParameterAnnotationsForLambdaTest extends RuntimeParameterAn } } + protected void testAttributes( + TestCase.TestMethodInfo testMethod, + ClassFile classFile, + Method method) throws ConstantPoolException { + Attributes attributes = method.attributes; + RuntimeParameterAnnotations_attribute attr = (RuntimeParameterAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleParameterAnnotations); + checkNull(attr, String.format("%s should be null", Attribute.RuntimeInvisibleParameterAnnotations)); + attr = (RuntimeParameterAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleParameterAnnotations); + checkNull(attr, String.format("%s should be null", Attribute.RuntimeVisibleParameterAnnotations)); + } + public String generateLambdaSource(TestCase.TestMethodInfo method) { return method.parameters.stream() .map(TestCase.TestParameterInfo::generateSource) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/StartupEventListener.java b/langtools/test/tools/javac/diags/examples/HideStatic.java similarity index 78% rename from hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/StartupEventListener.java rename to langtools/test/tools/javac/diags/examples/HideStatic.java index a67e04c0750aa1d3d0dbfd03e6efbd2b5b71b7af..1d49907e851260a41969cdea96b91f74ff95286e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/StartupEventListener.java +++ b/langtools/test/tools/javac/diags/examples/HideStatic.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,12 +20,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.vm.ci.compiler; -public interface StartupEventListener { +// key: compiler.err.override.incompatible.ret +// key: compiler.misc.cant.hide - /** - * This method is called before any of the {@link CompilerFactory} methods. - */ - void beforeJVMCIStartup(); +class Base { + static void func() { } +} + +class HideStatic extends Base { + static int func() { return 0; } } diff --git a/langtools/test/tools/javac/generics/inference/8141613/T8141613.java b/langtools/test/tools/javac/generics/inference/8141613/T8141613.java new file mode 100644 index 0000000000000000000000000000000000000000..44c6710ca2c0f9d4ed2ae19bd7d42849b30d9733 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/8141613/T8141613.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. 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. + */ + +/* + * @test + * @bug 8141613 + * @summary Compiler fails to infer generic type + * @compile T8141613.java + */ +class T8141613 { + + static class Sub<V, L> implements Sup<V, L> { + Sub(Bar<V> barv) { } + } + + interface Bar<V> { } + + interface Sup<V, L> { } + + <L> void test() { + Sup<?, L> res1 = makeSub(makeBar()); + Sup<?, L> res2 = new Sub<>(makeBar()); + } + + <S, U> Sub<S, U> makeSub(Bar<S> bars) { return null; } + + <B> Bar<?> makeBar() { + return null; + } +} diff --git a/langtools/test/tools/javac/lambda/SE5AnnotationsOnLambdaParameters.java b/langtools/test/tools/javac/lambda/SE5AnnotationsOnLambdaParameters.java new file mode 100644 index 0000000000000000000000000000000000000000..1079edd51686778d6a23b1a56c6d3c5a45abf11c --- /dev/null +++ b/langtools/test/tools/javac/lambda/SE5AnnotationsOnLambdaParameters.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. + */ + +/* + * @test + * @bug 8138612 + * @summary Do not retain declaration annotations on lambda formal parameters + * @run main SE5AnnotationsOnLambdaParameters + */ + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; + +public class SE5AnnotationsOnLambdaParameters { + @Retention(RetentionPolicy.RUNTIME) + @interface Annot {} + + interface Runnable { + void run(int x); + } + + public void run(Runnable r) {} + + public static void main(@Annot String [] args) throws ClassNotFoundException { + new SE5AnnotationsOnLambdaParameters().run((@Annot int x) -> { System.out.println(x + args.length); }); + Class<?> clazz = Class.forName("SE5AnnotationsOnLambdaParameters"); + for (Method m : clazz.getDeclaredMethods()) { + if (m.getName().startsWith("lambda$")) { + for (Annotation[] annots : m.getParameterAnnotations()) { + if (annots.length > 0) { + throw new AssertionError("Unexpected annotations on lambda parameters"); + } + } + } + } + } +} \ No newline at end of file diff --git a/langtools/test/tools/javac/lambda/T8129740/AllowEnclosingVarCaptureTest.java b/langtools/test/tools/javac/lambda/T8129740/AllowEnclosingVarCaptureTest.java new file mode 100644 index 0000000000000000000000000000000000000000..63121693ee20fd11928b7bcf9efbc0d1772dc71c --- /dev/null +++ b/langtools/test/tools/javac/lambda/T8129740/AllowEnclosingVarCaptureTest.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. + */ + +/* + * @test + * @bug 8129740 8133111 + * @summary Incorrect class file created when passing lambda in inner class constructor + * @run main AllowEnclosingVarCaptureTest + */ + +public class AllowEnclosingVarCaptureTest { + + int var = 0; + + void foo() { + var *= 2; + } + + public static void main(String[] args) { + new AllowEnclosingVarCaptureTest().new Inner(9764); + } + + public class Inner { + public Inner(Runnable r) { + r.run(); + if (var != 66704) + throw new AssertionError("Unexpected output: " + var); + } + + public Inner(int x) { + this(() -> { + var = x + 1234; + AllowEnclosingVarCaptureTest.this.var += 5678; + foo(); + AllowEnclosingVarCaptureTest.this.foo(); + }); + } + } +} diff --git a/langtools/test/tools/javac/lambda/T8129740/CaptureInCtorChainingTest.java b/langtools/test/tools/javac/lambda/T8129740/CaptureInCtorChainingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5548756927f5882561796f733fa600ca1c6491fe --- /dev/null +++ b/langtools/test/tools/javac/lambda/T8129740/CaptureInCtorChainingTest.java @@ -0,0 +1,54 @@ +/* + * 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 8129740 8133111 + * @summary Incorrect class file created when passing lambda in inner class constructor + * @run main CaptureInCtorChainingTest + */ + +import java.util.function.Consumer; +import java.util.function.Function; + +public class CaptureInCtorChainingTest { + + CaptureInCtorChainingTest(Function<Function<Function<Consumer<Void>, Void>, Void>, Void> innerClass) { + new InnerClass(innerClass); + } + + void foo(Void v) { } + + class InnerClass { + + InnerClass(Function<Function<Function<Consumer<Void>, Void>, Void>, Void> factory) { + this(factory.apply(o -> o.apply(CaptureInCtorChainingTest.this::foo))); + } + + InnerClass(Void unused) { } + } + + public static void main(String[] args) { + new CaptureInCtorChainingTest(o -> null); + } +} diff --git a/langtools/test/tools/javac/lambda/T8129740/QualifiedThisAccessTest.java b/langtools/test/tools/javac/lambda/T8129740/QualifiedThisAccessTest.java new file mode 100644 index 0000000000000000000000000000000000000000..50356a872ac2a0fca50b7b073e7cca48a1e6ed43 --- /dev/null +++ b/langtools/test/tools/javac/lambda/T8129740/QualifiedThisAccessTest.java @@ -0,0 +1,157 @@ +/* + * 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 8129740 8133111 + * @summary Incorrect class file created when passing lambda in inner class constructor + * @run main QualifiedThisAccessTest + */ + +public class QualifiedThisAccessTest { // Not referenced by lambda, so should not be captured. + + public class Universe { // Not referenced by lambda, so should not be captured. + + public String name; + public int galaxiesCount; + + public Universe(String name, int galaxiesCount) { + this.name = name; + this.galaxiesCount = galaxiesCount; + } + + public String toString() { + return "Universe" + name + " of " + galaxiesCount + " galaxies"; + } + + class Galaxy { + + String name; + private int starsCount; + + Galaxy(String name, int starsCount) { + this.name = name; + this.starsCount = starsCount; + } + + public String toString() { + return "galaxy " + name + " of " + starsCount + " solar systems"; + } + + int starsCount() { + return starsCount; + } + + private String name() { + return name; + } + + class SolarSystem { + + String name; + int planetsCount; + + SolarSystem(String name, int planetsCount) { + this.name = name; + this.planetsCount = planetsCount; + } + + public String toString() { + return "Solar System of " + name + " with " + planetsCount + " planets"; + } + + int planetsCount() { + return planetsCount; + } + + SolarSystem copy(SolarSystem s) { + return s; + } + + class Planet { + + String name; + int moonsCount; + + Planet(String name, int moonsCount, Runnable r) { + this.name = name; + this.moonsCount = moonsCount; + r.run(); + } + Planet (String name, int moonsCount) { + this(name, moonsCount, ()-> { + StringBuffer buf = new StringBuffer(); + buf.append("This planet belongs to the galaxy " + + Galaxy.this.name + " with " + starsCount + " stars\n"); + buf.append("This planet belongs to the galaxy " + + Universe.Galaxy.this.name + " with " + starsCount() + " stars\n"); + buf.append("This planet belongs to the galaxy " + + Galaxy.this.name() + " with " + starsCount() + " stars\n"); + buf.append("This planet belongs to the galaxy " + + Universe.Galaxy.this.name() + " with " + + (Universe.Galaxy.this).starsCount() + " stars\n"); + + buf.append("This planet belongs to the solar system " + + SolarSystem.this.name + " with " + planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + + Galaxy.SolarSystem.this.name + " with " + planetsCount() + " planets\n"); + buf.append("This planet belongs to the solar system " + + (SolarSystem.this).name + " with " + planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + + Universe.Galaxy.SolarSystem.this.name + " with " + + Universe.Galaxy.SolarSystem.this.planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + + Universe.Galaxy.SolarSystem.this.name.toLowerCase().toUpperCase() + + " with " + Universe.Galaxy.SolarSystem.this.planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + + copy(Universe.Galaxy.SolarSystem.this).name.toLowerCase().toUpperCase() + + " with " + Universe.Galaxy.SolarSystem.this.planetsCount + " planets\n"); + if (!buf.toString().equals(output)) + throw new AssertionError("Unexpected value\n" + buf); + }); + } + + static final String output = + "This planet belongs to the galaxy Mily way with 23456789 stars\n" + + "This planet belongs to the galaxy Mily way with 23456789 stars\n" + + "This planet belongs to the galaxy Mily way with 23456789 stars\n" + + "This planet belongs to the galaxy Mily way with 23456789 stars\n" + + "This planet belongs to the solar system Sun with 9 planets\n" + + "This planet belongs to the solar system Sun with 9 planets\n" + + "This planet belongs to the solar system Sun with 9 planets\n" + + "This planet belongs to the solar system Sun with 9 planets\n" + + "This planet belongs to the solar system SUN with 9 planets\n" + + "This planet belongs to the solar system SUN with 9 planets\n"; + + + public String toString() { + return "Planet " + name + " with " + moonsCount + " moon(s)"; + } + } + } + } + } + public static void main(String[] args) { + new QualifiedThisAccessTest().new Universe("Universe", 12345678).new Galaxy("Mily way", 23456789).new SolarSystem("Sun", 9).new Planet("Earth", 1); + } +} diff --git a/langtools/test/tools/javac/lambda/T8129740/SourceForTranslation.java b/langtools/test/tools/javac/lambda/T8129740/SourceForTranslation.java new file mode 100644 index 0000000000000000000000000000000000000000..1fd7d38c2db365a6b3a8bba48a1043e7573f4a61 --- /dev/null +++ b/langtools/test/tools/javac/lambda/T8129740/SourceForTranslation.java @@ -0,0 +1,122 @@ + class Universe { // Not referenced by lambda, so should not be captured. + + public String name; + public int galaxiesCount; + + public Universe(String name, int galaxiesCount) { + this.name = name; + this.galaxiesCount = galaxiesCount; + } + + public String toString() { + return "Universe" + name + " of " + galaxiesCount + " galaxies"; + } + + class Galaxy { + + String name; + private int starsCount; + + Galaxy(String name, int starsCount) { + this.name = name; + this.starsCount = starsCount; + } + + public String toString() { + return "galaxy " + name + " of " + starsCount + " solar systems"; + } + + int starsCount() { + return starsCount; + } + + private String name() { + return name; + } + + class SolarSystem { + + String name; + int planetsCount; + + SolarSystem(String name, int planetsCount) { + this.name = name; + this.planetsCount = planetsCount; + } + + public String toString() { + return "Solar System of " + name + " with " + planetsCount + " planets"; + } + + int planetsCount() { + return planetsCount; + } + + SolarSystem copy(SolarSystem s) { + return s; + } + + class Planet { + + String name; + int moonsCount; + + Planet(String name, int moonsCount, Runnable r) { + this.name = name; + this.moonsCount = moonsCount; + r.run(); + } + Planet (String name, int moonsCount) { + this(name, moonsCount, ()-> { + String n = name; + StringBuffer buf = new StringBuffer(); + buf.append("This planet belongs to the galaxy " + + Galaxy.this.name + " with " + starsCount + " stars\n"); + buf.append("This planet belongs to the galaxy " + + Universe.Galaxy.this.name + " with " + starsCount() + " stars\n"); + buf.append("This planet belongs to the galaxy " + + Galaxy.this.name() + " with " + starsCount() + " stars\n"); + buf.append("This planet belongs to the galaxy " + + Universe.Galaxy.this.name() + " with " + + (Universe.Galaxy.this).starsCount() + " stars\n"); + + buf.append("This planet belongs to the solar system " + + SolarSystem.this.name + " with " + planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + + Galaxy.SolarSystem.this.name + " with " + planetsCount() + " planets\n"); + buf.append("This planet belongs to the solar system " + + (SolarSystem.this).name + " with " + planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + + Universe.Galaxy.SolarSystem.this.name + " with " + + Universe.Galaxy.SolarSystem.this.planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + + Universe.Galaxy.SolarSystem.this.name.toLowerCase().toUpperCase() + + " with " + Universe.Galaxy.SolarSystem.this.planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + + copy(Universe.Galaxy.SolarSystem.this).name.toLowerCase().toUpperCase() + + " with " + Universe.Galaxy.SolarSystem.this.planetsCount + " planets\n"); + if (!buf.toString().equals(output)) + throw new AssertionError("Unexpected value\n" + buf); + }); + } + + static final String output = + "This planet belongs to the galaxy Mily way with 23456789 stars\n" + + "This planet belongs to the galaxy Mily way with 23456789 stars\n" + + "This planet belongs to the galaxy Mily way with 23456789 stars\n" + + "This planet belongs to the galaxy Mily way with 23456789 stars\n" + + "This planet belongs to the solar system Sun with 9 planets\n" + + "This planet belongs to the solar system Sun with 9 planets\n" + + "This planet belongs to the solar system Sun with 9 planets\n" + + "This planet belongs to the solar system Sun with 9 planets\n" + + "This planet belongs to the solar system SUN with 9 planets\n" + + "This planet belongs to the solar system SUN with 9 planets\n"; + + + public String toString() { + return "Planet " + name + " with " + moonsCount + " moon(s)"; + } + } + } + } + } diff --git a/langtools/test/tools/javac/lambda/T8129740/SourceToSourceTranslationTest.java b/langtools/test/tools/javac/lambda/T8129740/SourceToSourceTranslationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..eb6ee359b033721bbde2ac285683ec75afc9dcd9 --- /dev/null +++ b/langtools/test/tools/javac/lambda/T8129740/SourceToSourceTranslationTest.java @@ -0,0 +1,53 @@ +/* + * 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 8129740 8133111 + * @summary Incorrect class file created when passing lambda in inner class constructor + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.file + * jdk.compiler/com.sun.tools.javac.main + * @build ToolBox + * @run compile -XD-printsource SourceForTranslation.java + * @run main SourceToSourceTranslationTest + */ + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +public class SourceToSourceTranslationTest { + + public static void main(String[] args) throws Exception { + ToolBox tb = new ToolBox(); + Path path1 = Paths.get(ToolBox.testClasses, "Universe.java"); + List<String> file1 = tb.readAllLines(path1); + + Path path2 = Paths.get(ToolBox.testSrc, "Universe.java.out"); + List<String> file2 = tb.readAllLines(path2); + tb.checkEqual(file1, file2); + } + +} diff --git a/langtools/test/tools/javac/lambda/T8129740/Universe.java.out b/langtools/test/tools/javac/lambda/T8129740/Universe.java.out new file mode 100644 index 0000000000000000000000000000000000000000..1d8c0e290c29ea6071d97b78da40a49989ab804a --- /dev/null +++ b/langtools/test/tools/javac/lambda/T8129740/Universe.java.out @@ -0,0 +1,98 @@ + +class Universe { + public String name; + public int galaxiesCount; + + public Universe(String name, int galaxiesCount) { + super(); + this.name = name; + this.galaxiesCount = galaxiesCount; + } + + public String toString() { + return "Universe" + name + " of " + galaxiesCount + " galaxies"; + } + + class Galaxy { + String name; + private int starsCount; + + Galaxy(String name, int starsCount) { + super(); + this.name = name; + this.starsCount = starsCount; + } + + public String toString() { + return "galaxy " + name + " of " + starsCount + " solar systems"; + } + + int starsCount() { + return starsCount; + } + + private String name() { + return name; + } + + class SolarSystem { + String name; + int planetsCount; + + SolarSystem(String name, int planetsCount) { + super(); + this.name = name; + this.planetsCount = planetsCount; + } + + public String toString() { + return "Solar System of " + name + " with " + planetsCount + " planets"; + } + + int planetsCount() { + return planetsCount; + } + + SolarSystem copy(SolarSystem s) { + return s; + } + + class Planet { + String name; + int moonsCount; + + Planet(String name, int moonsCount, Runnable r) { + super(); + this.name = name; + this.moonsCount = moonsCount; + r.run(); + } + + Planet(String name, int moonsCount) { + this(name, moonsCount, java.lang.invoke.LambdaMetafactory.metafactory(name, Universe.Galaxy.this, Universe.Galaxy.SolarSystem.this)); + } + static final String output = "This planet belongs to the galaxy Mily way with 23456789 stars\nThis planet belongs to the galaxy Mily way with 23456789 stars\nThis planet belongs to the galaxy Mily way with 23456789 stars\nThis planet belongs to the galaxy Mily way with 23456789 stars\nThis planet belongs to the solar system Sun with 9 planets\nThis planet belongs to the solar system Sun with 9 planets\nThis planet belongs to the solar system Sun with 9 planets\nThis planet belongs to the solar system Sun with 9 planets\nThis planet belongs to the solar system SUN with 9 planets\nThis planet belongs to the solar system SUN with 9 planets\n"; + + public String toString() { + return "Planet " + name + " with " + moonsCount + " moon(s)"; + } + + /*synthetic*/ private static void lambda$new$0(/*synthetic*/ final String name, /*synthetic*/ final Universe.Galaxy Universe$Galaxy$this, /*synthetic*/ final Universe.Galaxy.SolarSystem Universe$Galaxy$SolarSystem$this) { + String n = name; + StringBuffer buf = new StringBuffer(); + buf.append("This planet belongs to the galaxy " + Universe$Galaxy$this.name + " with " + Universe$Galaxy$this.starsCount + " stars\n"); + buf.append("This planet belongs to the galaxy " + Universe$Galaxy$this.name + " with " + Universe$Galaxy$this.starsCount() + " stars\n"); + buf.append("This planet belongs to the galaxy " + Universe$Galaxy$this.name() + " with " + Universe$Galaxy$this.starsCount() + " stars\n"); + buf.append("This planet belongs to the galaxy " + Universe$Galaxy$this.name() + " with " + (Universe$Galaxy$this).starsCount() + " stars\n"); + buf.append("This planet belongs to the solar system " + Universe$Galaxy$SolarSystem$this.name + " with " + Universe$Galaxy$SolarSystem$this.planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + Universe$Galaxy$SolarSystem$this.name + " with " + Universe$Galaxy$SolarSystem$this.planetsCount() + " planets\n"); + buf.append("This planet belongs to the solar system " + (Universe$Galaxy$SolarSystem$this).name + " with " + Universe$Galaxy$SolarSystem$this.planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + Universe$Galaxy$SolarSystem$this.name + " with " + Universe$Galaxy$SolarSystem$this.planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + Universe$Galaxy$SolarSystem$this.name.toLowerCase().toUpperCase() + " with " + Universe$Galaxy$SolarSystem$this.planetsCount + " planets\n"); + buf.append("This planet belongs to the solar system " + Universe$Galaxy$SolarSystem$this.copy(Universe$Galaxy$SolarSystem$this).name.toLowerCase().toUpperCase() + " with " + Universe$Galaxy$SolarSystem$this.planetsCount + " planets\n"); + if (!buf.toString().equals(output)) throw new AssertionError("Unexpected value\n" + buf); + } + } + } + } +} diff --git a/langtools/test/tools/javac/lambda/methodReference/IntersectionTypeReceiverTest.java b/langtools/test/tools/javac/lambda/methodReference/IntersectionTypeReceiverTest.java new file mode 100644 index 0000000000000000000000000000000000000000..62b54bd492bd7634bfc530ca3b5da729752b19f1 --- /dev/null +++ b/langtools/test/tools/javac/lambda/methodReference/IntersectionTypeReceiverTest.java @@ -0,0 +1,64 @@ +/* + * 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 8141508 + * @summary Test that Call site initialization exception is not thrown when the method + reference receiver is of intersection type. + * @run main IntersectionTypeReceiverTest + */ + +import java.time.LocalDate; +import java.util.EnumSet; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +public class IntersectionTypeReceiverTest { + + public static void main(String[] args) { + String output = valueOfKey(Size.class, LocalDate.now()).toString(); + if (!"Optional[S]".equals(output)) + throw new AssertionError("Unexpected output: " + output); + } + + enum Size implements Supplier<LocalDate> { + S, M, L; + + @Override + public LocalDate get() { + return LocalDate.now(); + } + + } + + public static <K, T extends Enum<T> & Supplier<K>> Optional<T> valueOfKey(Class<T> enumType, K key) { + return valueOf(enumType, key, T::get); + } + + public static <K, T extends Enum<T>> Optional<T> valueOf(Class<T> enumType, K key, Function<T, K> keyExtractor) { + return EnumSet.allOf(enumType).stream().filter(t -> Objects.equals(keyExtractor.apply(t), key)).findFirst(); + } +} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SuppressFBWarnings.java b/langtools/test/tools/javac/lambda/methodReference/IntersectionTypeReceiverTest2.java similarity index 61% rename from hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SuppressFBWarnings.java rename to langtools/test/tools/javac/lambda/methodReference/IntersectionTypeReceiverTest2.java index c9567f722841cda934442aa3d372868021849c76..76f384dddb87a774c7212661be2033272001b160 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SuppressFBWarnings.java +++ b/langtools/test/tools/javac/lambda/methodReference/IntersectionTypeReceiverTest2.java @@ -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 @@ -20,21 +20,32 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.vm.ci.hotspot; /** - * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings. + * @test + * @bug 8142476 + * @summary Test that Call site initialization exception is not thrown when the method + reference receiver is of intersection type. + * @run main IntersectionTypeReceiverTest2 */ -public @interface SuppressFBWarnings { - /** - * The set of FindBugs <a - * href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be - * suppressed in annotated element. The value can be a bug category, kind or pattern. - */ - String[] value(); - /** - * Reason why the warning is suppressed. - */ - String justification(); +public class IntersectionTypeReceiverTest2 { + interface I { + } + + interface J { + void foo(); + } + + static <T extends I & J> void bar(T t) { + Runnable r = t::foo; + } + + public static void main(String[] args) { + class A implements I, J { + public void foo() { + } + } + bar(new A()); + } } diff --git a/make/BuildStatic.gmk b/make/BuildStatic.gmk new file mode 100644 index 0000000000000000000000000000000000000000..0fc166a10f34118c3f10b0bb897738b304299fad --- /dev/null +++ b/make/BuildStatic.gmk @@ -0,0 +1,54 @@ +# +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk + +################################################################################ +# +# Concatenate exported.symbols files for modules into a single global file. +# + +GLOBAL_SYMBOLS_FILE := $(SUPPORT_OUTPUTDIR)/build-static/exported.symbols + +EXPORTED_SYMBOLS_MODULES := java.base jdk.jdwp.agent + +MODULES_SYMBOLS_FILES := $(foreach module, $(EXPORTED_SYMBOLS_MODULES), \ + $(SUPPORT_OUTPUTDIR)/modules_libs/$(module)/$(module).symbols) + +$(GLOBAL_SYMBOLS_FILE): $(MODULES_SYMBOLS_FILES) + $(ECHO) $(LOG_INFO) "Generating global exported.symbols file" + $(MKDIR) -p $(@D) + $(CAT) $^ > $@ + +TARGETS += $(GLOBAL_SYMBOLS_FILE) + +################################################################################ + +all: $(TARGETS) + +.PHONY: default all diff --git a/make/Init.gmk b/make/Init.gmk index b2aa7ce7a22b6bddbf356ed87b41e69be0889d7c..3627d12579caee0c679353472959bd8deeacf04f 100644 --- a/make/Init.gmk +++ b/make/Init.gmk @@ -305,49 +305,20 @@ else # HAS_SPEC=true endif on-failure: - ifneq ($(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*), ) - $(PRINTF) "=== Output from failing command(s) repeated here ===\n" - $(foreach logfile, $(sort $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*)), \ - $(PRINTF) "* For target $(notdir $(basename $(logfile))):\n" $(NEWLINE) \ - $(CAT) $(logfile) | $(GREP) -v -e "^Note: including file:" $(NEWLINE) \ - ) - $(PRINTF) "=== End of repeated output ===\n" - endif - if $(GREP) -q "recipe for target .* failed" $(BUILD_LOG) 2> /dev/null; then \ - $(PRINTF) "=== Make failure sequence repeated here ===\n" ; \ - $(GREP) "recipe for target .* failed" $(BUILD_LOG) ; \ - $(PRINTF) "=== End of repeated output ===\n" ; \ - $(PRINTF) "Hint: Try searching the build log for the name of the first failed target.\n" ; \ - else \ - $(PRINTF) "No indication of failed target found.\n" ; \ - $(PRINTF) "Hint: Try searching the build log for '] Error'.\n" ; \ - fi + $(call PrintFailureReports) + $(call PrintBuildLogFailures) $(PRINTF) "Hint: If caused by a warning, try configure --disable-warnings-as-errors.\n\n" + ifneq ($(COMPARE_BUILD), ) + $(call CleanupCompareBuild) + endif # Support targets for COMPARE_BUILD, used for makefile development pre-compare-build: - $(ECHO) "Preparing for comparison rebuild" - # Apply patch, if any - ifneq ($(COMPARE_BUILD_PATCH), ) - $(PATCH) -p1 < $(COMPARE_BUILD_PATCH) - endif - # Move the first build away and re-create the output directory - ( cd $(TOPDIR) && \ - $(MV) $(OUTPUT_ROOT) $(OUTPUT_ROOT).OLD && \ - $(MKDIR) -p $(OUTPUT_ROOT) ) - # Re-run configure with the same arguments (and possibly some additional), - # must be done after patching. - ( cd $(OUTPUT_ROOT) && PATH="$(ORIGINAL_PATH)" \ - $(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF)) + $(call PrepareCompareBuild) post-compare-build: - # Compare first and second build. Ignore any error code from compare.sh. - $(ECHO) "Comparing between comparison rebuild (this/new) and baseline (other/old)" - ifneq ($(COMPARE_BUILD_COMP_DIR), ) - +(cd $(OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) -2dirs $(OUTPUT_ROOT)/$(COMPARE_BUILD_COMP_DIR) $(OUTPUT_ROOT).OLD/$(COMPARE_BUILD_COMP_DIR) || true) - else - +(cd $(OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) -o $(OUTPUT_ROOT).OLD || true) - endif + $(call CleanupCompareBuild) + $(call CompareBuildDoComparison) .PHONY: print-targets print-modules reconfigure main on-failure endif diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 61719916a27ad3a6b03671e2b1efc318c7bed5ee..66ad3e9f0965b0950a6bf755ff5283d262b24483 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -321,6 +321,8 @@ else # $(HAS_SPEC)=true # If any value contains "+", it will be replaced by space. define ParseCompareBuild ifneq ($$(COMPARE_BUILD), ) + COMPARE_BUILD_OUTPUT_ROOT := $(TOPDIR)/build/compare-build/$(CONF_NAME) + ifneq ($$(findstring :, $$(COMPARE_BUILD)), ) $$(foreach part, $$(subst :, , $$(COMPARE_BUILD)), \ $$(if $$(filter PATCH=%, $$(part)), \ @@ -364,6 +366,73 @@ else # $(HAS_SPEC)=true endif endef + # Prepare for a comparison rebuild + define PrepareCompareBuild + $(ECHO) "Preparing for comparison rebuild" + # Apply patch, if any + $(if $(COMPARE_BUILD_PATCH), $(PATCH) -p1 < $(COMPARE_BUILD_PATCH)) + # Move the first build away temporarily + $(RM) -r $(TOPDIR)/build/.compare-build-temp + $(MKDIR) -p $(TOPDIR)/build/.compare-build-temp + $(MV) $(OUTPUT_ROOT) $(TOPDIR)/build/.compare-build-temp + # Restore an old compare-build, or create a new compare-build directory. + if test -d $(COMPARE_BUILD_OUTPUT_ROOT); then \ + $(MV) $(COMPARE_BUILD_OUTPUT_ROOT) $(OUTPUT_ROOT); \ + else \ + $(MKDIR) -p $(OUTPUT_ROOT); \ + fi + # Re-run configure with the same arguments (and possibly some additional), + # must be done after patching. + ( cd $(OUTPUT_ROOT) && PATH="$(ORIGINAL_PATH)" \ + $(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF)) + endef + + # Cleanup after a compare build + define CleanupCompareBuild + # If running with a COMPARE_BUILD patch, reverse-apply it + $(if $(COMPARE_BUILD_PATCH), $(PATCH) -R -p1 < $(COMPARE_BUILD_PATCH)) + # Move this build away and restore the original build + $(MKDIR) -p $(TOPDIR)/build/compare-build + $(MV) $(OUTPUT_ROOT) $(COMPARE_BUILD_OUTPUT_ROOT) + $(MV) $(TOPDIR)/build/.compare-build-temp/$(CONF_NAME) $(OUTPUT_ROOT) + $(RM) -r $(TOPDIR)/build/.compare-build-temp + endef + + # Do the actual comparison of two builds + define CompareBuildDoComparison + # Compare first and second build. Ignore any error code from compare.sh. + $(ECHO) "Comparing between comparison rebuild (this/new) and baseline (other/old)" + $(if $(COMPARE_BUILD_COMP_DIR), \ + +(cd $(COMPARE_BUILD_OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) \ + -2dirs $(COMPARE_BUILD_OUTPUT_ROOT)/$(COMPARE_BUILD_COMP_DIR) $(OUTPUT_ROOT)/$(COMPARE_BUILD_COMP_DIR) || true), \ + +(cd $(COMPARE_BUILD_OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) \ + -o $(OUTPUT_ROOT) || true) \ + ) + endef + + define PrintFailureReports + $(if $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*), \ + $(PRINTF) "=== Output from failing command(s) repeated here ===\n" $(NEWLINE) \ + $(foreach logfile, $(sort $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*)), \ + $(PRINTF) "* For target $(notdir $(basename $(logfile))):\n" $(NEWLINE) \ + $(CAT) $(logfile) | $(GREP) -v -e "^Note: including file:" $(NEWLINE) \ + ) \ + $(PRINTF) "=== End of repeated output ===\n" \ + ) + endef + + define PrintBuildLogFailures + if $(GREP) -q "recipe for target .* failed" $(BUILD_LOG) 2> /dev/null; then \ + $(PRINTF) "=== Make failure sequence repeated here ===\n" ; \ + $(GREP) "recipe for target .* failed" $(BUILD_LOG) ; \ + $(PRINTF) "=== End of repeated output ===\n" ; \ + $(PRINTF) "Hint: Try searching the build log for the name of the first failed target.\n" ; \ + else \ + $(PRINTF) "No indication of failed target found.\n" ; \ + $(PRINTF) "Hint: Try searching the build log for '] Error'.\n" ; \ + fi + endef + define RotateLogFiles $(RM) $(BUILD_LOG).old 2> /dev/null $(MV) $(BUILD_LOG) $(BUILD_LOG).old 2> /dev/null || true diff --git a/make/Main.gmk b/make/Main.gmk index 6446c1b7712187dec4ff50dab3fe03b627bfe390..ea251fa8a6978e996204c2a1fdd847bbf1524d1a 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -93,7 +93,10 @@ import-hotspot: unpack-sec: +($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f UnpackSecurity.gmk) -ALL_TARGETS += import-hotspot unpack-sec +generate-exported-symbols: + +($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f BuildStatic.gmk) + +ALL_TARGETS += import-hotspot unpack-sec generate-exported-symbols ################################################################################ # Gensrc targets, generating source before java compilation can be done @@ -298,16 +301,23 @@ ALL_TARGETS += prepare-test-image build-test-hotspot-jtreg-native \ test: $(call RunTests, $(TEST)) +test-hotspot-jtreg: + $(call RunTests, "hotspot_all") + test-hotspot-jtreg-native: $(call RunTests, "hotspot_native_sanity") +test-hotspot-internal: + $(call RunTests, "hotspot_internal") + test-jdk-jtreg-native: $(call RunTests, "jdk_native_sanity") test-make: ($(CD) $(SRC_ROOT)/test/make && $(MAKE) $(MAKE_ARGS) -f TestMake.gmk $(TEST_TARGET)) -ALL_TARGETS += test test-hotspot-jtreg-native test-jdk-jtreg-native test-make +ALL_TARGETS += test test-hotspot-jtreg test-hotspot-jtreg-native \ + test-hotspot-internal test-jdk-jtreg-native test-make ################################################################################ # Verification targets @@ -368,10 +378,16 @@ else import-hotspot: hotspot + generate-exported-symbols: java.base-libs jdk.jdwp.agent-libs + $(LIBS_TARGETS): import-hotspot $(LAUNCHER_TARGETS): java.base-libs + ifeq ($(STATIC_BUILD), true) + $(LAUNCHER_TARGETS): generate-exported-symbols + endif + # The demos are currently linking to libjvm and libjava, just like all other # jdk libs, even though they don't need to. To avoid warnings, make sure they # aren't built until after libjava and libjvm are available to link to. @@ -462,6 +478,10 @@ else test-image-jdk-jtreg-native: build-test-jdk-jtreg-native + test-hotspot-internal: exploded-image + + test-hotspot-jtreg: jimages test-image + endif ################################################################################ diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index a52f92eb526ca3904eea5f485d033aae06bfbf5c..d55217134486bacd87d724124baf198672a4fbf1 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -34,6 +34,31 @@ ifeq (,$(_MAKEBASE_GMK)) $(error You must include MakeBase.gmk prior to including NativeCompilation.gmk) endif +################################################################################ +# Create exported symbols file for static libraries +################################################################################ + +# get the exported symbols from mapfiles and if there +# is no mapfile, get them from the archive +define GetSymbols + $(RM) $$(@D)/$$(basename $$(@F)).symbols; \ + if [ ! -z $$($1_MAPFILE) -a -e $$($1_MAPFILE) ]; then \ + $(ECHO) "Getting symbols from mapfile $$($1_MAPFILE)"; \ + $(AWK) '/global:/','/local:/' $$($1_MAPFILE) | \ + $(SED) -e 's/#.*//;s/global://;s/local://;s/\;//;s/^[ ]*/_/;/^_$$$$/d' | \ + $(EGREP) -v "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" > \ + $$(@D)/$$(basename $$(@F)).symbols || true; \ + $(NM) $$($1_TARGET) | $(GREP) " T " | \ + $(EGREP) "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" | \ + $(CUT) -d ' ' -f 3 >> $$(@D)/$$(basename $$(@F)).symbols || true;\ + else \ + $(ECHO) "Getting symbols from nm"; \ + $(NM) -m $$($1_TARGET) | $(GREP) "__TEXT" | \ + $(EGREP) -v "non-external|private extern|__TEXT,__eh_frame" | \ + $(SED) -e 's/.* //' > $$(@D)/$$(basename $$(@F)).symbols; \ + fi +endef + ################################################################################ # Define a native toolchain configuration that can be used by # SetupNativeCompilation calls @@ -274,6 +299,15 @@ endef SetupNativeCompilation = $(NamedParamsMacroTemplate) define SetupNativeCompilationBody + # If we're doing a static build and producing a library + # force it to be a static library and remove the -l libraries + ifeq ($(STATIC_BUILD), true) + ifneq ($$($1_LIBRARY),) + $1_STATIC_LIBRARY := $$($1_LIBRARY) + $1_LIBRARY := + endif + endif + ifneq (,$$($1_BIN)) $$(error BIN has been replaced with OBJECT_DIR) endif @@ -495,6 +529,12 @@ define SetupNativeCompilationBody $1_EXTRA_CXXFLAGS += $$(CXX_FLAG_REORDER) endif + # Pass the library name for static JNI library naming + ifneq ($$($1_STATIC_LIBRARY),) + $1_EXTRA_CFLAGS += -DLIBRARY_NAME=$$($1_STATIC_LIBRARY) + $1_EXTRA_CXXFLAGS += -DLIBRARY_NAME=$$($1_STATIC_LIBRARY) + endif + # Pick up disabled warnings, if possible on this platform. ifneq ($(DISABLE_WARNING_PREFIX),) $1_EXTRA_CFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE))) @@ -725,7 +765,10 @@ define SetupNativeCompilationBody $(ECHO) $(LOG_INFO) "Archiving $$($1_STATIC_LIBRARY)" $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \ $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \ - $$($1_RES) $$($1_LIBS) $$($1_EXTRA_LIBS)) + $$($1_RES)) + ifeq ($(STATIC_BUILD), true) + $(GetSymbols) + endif endif ifneq (,$$($1_PROGRAM)) diff --git a/modules.xml b/modules.xml index 94b55f7c691453db6b9d6162470124c33a3bd531..8b04b0aba4f9d0b1c30c87972eab7170d4f8b9a5 100644 --- a/modules.xml +++ b/modules.xml @@ -229,8 +229,11 @@ <to>java.logging</to> <to>java.management</to> <to>java.naming</to> + <to>java.security.jgss</to> <to>java.sql</to> + <to>java.xml</to> <to>jdk.management.resource</to> + <to>jdk.scripting.nashorn</to> </export> <export> <name>jdk.internal.org.objectweb.asm</name> diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 29f3b1d5459c0af7205d3a4a0a27791c3248ad2e..de6ab20a83099d3bc588763e26e2746518fe4910 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -326,3 +326,4 @@ a2aa804daac974289e20bf8f9106740732f08b34 jdk9-b88 bc92163c4e0aa3fcca51a290c55715c54a5faa5f jdk9-b90 fee4d2015e24ced4f28f4dcf93076a4fbd03844d jdk9-b91 34b77a618e98c5da59a760341f43af6aefc56efb jdk9-b92 +e13533f7bb78da49bbd909fdf22e13e0e2538146 jdk9-b93 diff --git a/test/lib/sun/hotspot/code/CodeBlob.java b/test/lib/sun/hotspot/code/CodeBlob.java index a5097f1c7e40fc7fd2df903c930c3c9a71fecf81..72ba7a2dd1204013bf3cf794f12ec4b9ca499624 100644 --- a/test/lib/sun/hotspot/code/CodeBlob.java +++ b/test/lib/sun/hotspot/code/CodeBlob.java @@ -47,22 +47,24 @@ public class CodeBlob { return new CodeBlob(obj); } protected CodeBlob(Object[] obj) { - assert obj.length == 3; + assert obj.length == 4; name = (String) obj[0]; size = (Integer) obj[1]; code_blob_type = BlobType.values()[(Integer) obj[2]]; assert code_blob_type.id == (Integer) obj[2]; + address = (Long) obj[3]; } public final String name; public final int size; public final BlobType code_blob_type; - + public final long address; @Override public String toString() { return "CodeBlob{" + "name=" + name + ", size=" + size + ", code_blob_type=" + code_blob_type + + ", address=" + address + '}'; } } diff --git a/test/lib/sun/hotspot/code/NMethod.java b/test/lib/sun/hotspot/code/NMethod.java index 87f4b8faf866e5e8cce8116a49ed502d4357cb48..78b25443134c4645565a88fe838428d3d3cb52ba 100644 --- a/test/lib/sun/hotspot/code/NMethod.java +++ b/test/lib/sun/hotspot/code/NMethod.java @@ -39,12 +39,12 @@ public class NMethod extends CodeBlob { comp_level = (Integer) obj[1]; insts = (byte[]) obj[2]; compile_id = (Integer) obj[3]; - address = (Long) obj[4]; + entry_point = (Long) obj[4]; } public final byte[] insts; public final int comp_level; public final int compile_id; - public final long address; + public final long entry_point; @Override public String toString() { @@ -53,7 +53,7 @@ public class NMethod extends CodeBlob { + ", insts=" + insts + ", comp_level=" + comp_level + ", compile_id=" + compile_id - + ", address=" + address + + ", entry_point=" + entry_point + '}'; } }