OpenJDK / portola / portola
changeset 6246:2b94114ccaa4
Merge
author | kevinw |
---|---|
date | Sat, 31 Jul 2010 15:10:59 +0100 |
parents | c37d2cf6de1a c8dba9451894 |
children | 00e5cc407d03 |
files | corba/make/com/sun/corba/minclude/ioser_io.jmk hotspot/src/os/linux/vm/vtune_linux.cpp hotspot/src/os/solaris/vm/vtune_solaris.cpp hotspot/src/os/windows/vm/vtune_windows.cpp hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp hotspot/src/share/vm/runtime/vtune.hpp jdk/make/com/sun/inputmethods/Makefile jdk/make/com/sun/inputmethods/indicim/Makefile jdk/make/com/sun/inputmethods/thaiim/Makefile jdk/src/linux/doc/man/ja/kinit.1 jdk/src/linux/doc/man/ja/klist.1 jdk/src/linux/doc/man/ja/ktab.1 jdk/src/share/classes/com/sun/inputmethods/internal/indicim/DevanagariInputMethodDescriptor.java jdk/src/share/classes/com/sun/inputmethods/internal/indicim/DevanagariTables.java jdk/src/share/classes/com/sun/inputmethods/internal/indicim/IndicInputMethod.java jdk/src/share/classes/com/sun/inputmethods/internal/indicim/IndicInputMethodImpl.java jdk/src/share/classes/com/sun/inputmethods/internal/indicim/java.awt.im.spi.InputMethodDescriptor jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames.properties jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames_de.properties jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames_es.properties jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames_fr.properties jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames_it.properties jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames_ja.properties jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames_ko.properties jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames_sv.properties jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames_zh_CN.properties jdk/src/share/classes/com/sun/inputmethods/internal/indicim/resources/DisplayNames_zh_TW.properties jdk/src/share/classes/com/sun/inputmethods/internal/thaiim/ThaiInputMethod.java jdk/src/share/classes/com/sun/inputmethods/internal/thaiim/ThaiInputMethodDescriptor.java jdk/src/share/classes/com/sun/inputmethods/internal/thaiim/ThaiInputMethodImpl.java jdk/src/share/classes/com/sun/inputmethods/internal/thaiim/ThaiRules.java jdk/src/share/classes/com/sun/inputmethods/internal/thaiim/java.awt.im.spi.InputMethodDescriptor jdk/src/share/classes/com/sun/inputmethods/internal/thaiim/resources/DisplayNames.properties jdk/src/share/classes/javax/swing/text/html/parser/html32.bdtd jdk/src/share/classes/sun/security/tools/PolicyTool.java jdk/test/java/nio/channels/ServerSocketChannel/AcceptAddress.java jdk/test/java/nio/charset/coders/Surrogate.java jdk/test/tools/launcher/Makefile.SolarisRunpath jdk/test/tools/launcher/lib/i386/lib32/lib32/liblibrary.so jdk/test/tools/launcher/lib/i386/lib32/liblibrary.so jdk/test/tools/launcher/lib/sparc/lib32/lib32/liblibrary.so jdk/test/tools/launcher/lib/sparc/lib32/liblibrary.so jdk/test/tools/launcher/lib/sparc/lib64/lib64/liblibrary.so jdk/test/tools/launcher/lib/sparc/lib64/liblibrary.so |
diffstat | 1391 files changed, 47239 insertions(+), 22997 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Jul 30 22:43:50 2010 +0100 +++ b/.hgtags Sat Jul 31 15:10:59 2010 +0100 @@ -70,3 +70,9 @@ b5dab6a313fdff4c043250e4d9c8f66fd624d27e jdk7-b93 8bb281f0f91582104d65d032be22522bfd2d8110 jdk7-b94 654298d26561b76dfe3cfcffbbd7078080837300 jdk7-b95 +d260f892491e040ae385a8e6df59557a7d721abf jdk7-b96 +7e406ebed9a5968b584f3c3e6b60893b5d6d9741 jdk7-b97 +db6e660120446c407e2d908d52ec046592b21726 jdk7-b98 +c4c8a5bc54f66abc68cd185d9294042121922154 jdk7-b99 +2d6ba7a221915bdf0311acc5641c7f3875cb793e jdk7-b100 +2548ac036b8fca3326d058d758e6df8355a42469 jdk7-b101
--- a/.hgtags-top-repo Fri Jul 30 22:43:50 2010 +0100 +++ b/.hgtags-top-repo Sat Jul 31 15:10:59 2010 +0100 @@ -70,3 +70,9 @@ 5fc102ff48f0e787ce9cc77249841d5ff0941b75 jdk7-b93 d7f35c61afa092b6357c2c4bce3f298f16620f71 jdk7-b94 fd3663286e77b9f13c39eee124db2beb079b3ca6 jdk7-b95 +cf71cb5151166f35433afebaf67dbf34a704a170 jdk7-b96 +5e197c942c6ebd8b92f324a31049c5f1d26d40ef jdk7-b97 +6cea9984d73d74de0cd01f30d07ac0a1ed196117 jdk7-b98 +e7f18db469a3e947b7096bfd12e87380e5a042cd jdk7-b99 +b218a53ec7d3d42be61d31d6917a6c5c037b6f56 jdk7-b100 +4193eaf5f1b82794c6a0fb1a8d11af43d1b1d611 jdk7-b101
--- a/Makefile Fri Jul 30 22:43:50 2010 +0100 +++ b/Makefile Sat Jul 31 15:10:59 2010 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 1995, 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. # 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,6 @@ TOPDIR:=. endif -ifndef CONTROL_TOPDIR - CONTROL_TOPDIR=$(TOPDIR) -endif - # Openjdk sources (only used if SKIP_OPENJDK_BUILD!=true) OPENJDK_SOURCETREE=$(TOPDIR)/openjdk OPENJDK_BUILDDIR:=$(shell \ @@ -120,7 +116,7 @@ all_product_build:: @$(FINISH_ECHO) -# Generis build of basic repo series +# Generic build of basic repo series generic_build_repo_series:: $(MKDIR) -p $(OUTPUTDIR) $(MKDIR) -p $(OUTPUTDIR)/j2sdk-image @@ -179,11 +175,15 @@ # The install process needs to know what the DEBUG_NAME is, so # look for INSTALL_DEBUG_NAME in the install rules. # +# NOTE: On windows, do not use $(ABS_BOOTDIR_OUTPUTDIR)-$(DEBUG_NAME). +# Due to the use of short paths in $(ABS_OUTPUTDIR), this may +# not be the same location. +# # Location of fresh bootdir output ABS_BOOTDIR_OUTPUTDIR=$(ABS_OUTPUTDIR)/bootjdk FRESH_BOOTDIR=$(ABS_BOOTDIR_OUTPUTDIR)/j2sdk-image -FRESH_DEBUG_BOOTDIR=$(ABS_BOOTDIR_OUTPUTDIR)-$(DEBUG_NAME)/j2sdk-image +FRESH_DEBUG_BOOTDIR=$(ABS_BOOTDIR_OUTPUTDIR)/../$(PLATFORM)-$(ARCH)-$(DEBUG_NAME)/j2sdk-image create_fresh_product_bootdir: FRC @$(START_ECHO) @@ -248,10 +248,14 @@ generic_build_repo_series @$(FINISH_ECHO) +# NOTE: On windows, do not use $(ABS_OUTPUTDIR)-$(DEBUG_NAME). +# Due to the use of short paths in $(ABS_OUTPUTDIR), this may +# not be the same location. + generic_debug_build: @$(START_ECHO) $(MAKE) \ - ALT_OUTPUTDIR=$(ABS_OUTPUTDIR)-$(DEBUG_NAME) \ + ALT_OUTPUTDIR=$(ABS_OUTPUTDIR)/../$(PLATFORM)-$(ARCH)-$(DEBUG_NAME) \ DEBUG_NAME=$(DEBUG_NAME) \ GENERATE_DOCS=false \ $(BOOT_CYCLE_DEBUG_SETTINGS) \ @@ -348,8 +352,8 @@ clobber:: $(RM) -r $(OUTPUTDIR)/* - $(RM) -r $(OUTPUTDIR)-debug/* - $(RM) -r $(OUTPUTDIR)-fastdebug/* + $(RM) -r $(OUTPUTDIR)/../$(PLATFORM)-$(ARCH)-debug/* + $(RM) -r $(OUTPUTDIR)/../$(PLATFORM)-$(ARCH)-fastdebug/* -($(RMDIR) -p $(OUTPUTDIR) > $(DEV_NULL) 2>&1; $(TRUE)) clean: clobber @@ -551,6 +555,56 @@ endif ################################################################ +# rule to test +################################################################ + +.NOTPARALLEL: test + +test: test_clean test_start test_summary + +test_start: + @$(ECHO) "Tests started at `$(DATE)`" + +test_clean: + $(RM) $(OUTPUTDIR)/test_failures.txt $(OUTPUTDIR)/test_log.txt + +test_summary: $(OUTPUTDIR)/test_failures.txt + @$(ECHO) "#################################################" + @$(ECHO) "Tests completed at `$(DATE)`" + @( $(EGREP) '^TEST STATS:' $(OUTPUTDIR)/test_log.txt \ + || $(ECHO) "No TEST STATS seen in log" ) + @$(ECHO) "For complete details see: $(OUTPUTDIR)/test_log.txt" + @$(ECHO) "#################################################" + @if [ -s $< ] ; then \ + $(ECHO) "ERROR: Test failure count: `$(CAT) $< | $(WC) -l`"; \ + $(CAT) $<; \ + exit 1; \ + else \ + $(ECHO) "Success! No failures detected"; \ + fi + +# Get failure list from log +$(OUTPUTDIR)/test_failures.txt: $(OUTPUTDIR)/test_log.txt + @$(RM) $@ + @( $(EGREP) '^FAILED:' $< || $(ECHO) "" ) > $@ + +# Get log file of all tests run +JDK_TO_TEST := $(shell \ + if [ -d "$(ABS_OUTPUTDIR)/j2sdk-image" ] ; then \ + $(ECHO) "$(ABS_OUTPUTDIR)/j2sdk-image"; \ + elif [ -d "$(ABS_OUTPUTDIR)/bin" ] ; then \ + $(ECHO) "$(ABS_OUTPUTDIR)"; \ + elif [ "$(PRODUCT_HOME)" != "" -a -d "$(PRODUCT_HOME)/bin" ] ; then \ + $(ECHO) "$(PRODUCT_HOME)"; \ + fi \ +) +$(OUTPUTDIR)/test_log.txt: + $(RM) $@ + ( $(CD) test && \ + $(MAKE) NO_STOPPING=- PRODUCT_HOME=$(JDK_TO_TEST) \ + ) | tee $@ + +################################################################ # JPRT rule to build ################################################################ @@ -560,7 +614,7 @@ # PHONY ################################################################ -.PHONY: all \ +.PHONY: all test test_start test_summary test_clean \ generic_build_repo_series \ what clobber insane \ dev dev-build dev-sanity dev-clobber \
--- a/README-builds.html Fri Jul 30 22:43:50 2010 +0100 +++ b/README-builds.html Sat Jul 31 15:10:59 2010 +0100 @@ -65,8 +65,9 @@ <li><a href="#cacerts">Certificate Authority File (cacert)</a> </li> <li><a href="#compilers">Compilers</a> <ul> - <li><a href="#msvc">Microsoft Visual Studio</a> </li> - <li><a href="#mssdk">Microsoft Platform SDK</a> </li> + <li><a href="#msvc32">Microsoft Visual Studio Professional/Express for 32 bit</a> </li> + <li><a href="#msvc64">Microsoft Visual Studio Professional for 64 bit</a> </li> + <li><a href="#mssdk64">Microsoft Windows SDK for 64 bit</a> </li> <li><a href="#gcc">Linux gcc/binutils</a> </li> <li><a href="#studio">Sun Studio</a> </li> </ul> @@ -789,11 +790,11 @@ </li> <li> Install the - <a href="#msvc">Microsoft Visual Studio Compilers</a>). + <a href="#msvc32">Microsoft Visual Studio Compilers</a>). </li> <li> Setup all environment variables for compilers - (see <a href="#msvc">compilers</a>). + (see <a href="#msvc32">compilers</a>). </li> <li> Install @@ -958,7 +959,7 @@ are also an option, although these compilers have not been extensively used yet. </blockquote> - <strong><a name="msvc">Windows i586: Microsoft Visual Studio Compilers</a></strong> + <strong><a name="msvc32">Windows i586: Microsoft Visual Studio 2010 Compilers</a></strong> <blockquote> <p> <b>BEGIN WARNING</b>: At this time (Spring/Summer 2010) JDK 7 is starting a transition to @@ -971,14 +972,13 @@ We do not guarantee that VS2008 will work, although there is sufficient makefile support to make at least basic JDK builds plausible. Visual Studio 2010 Express compilers are now able to build all the -open source repositories, but this is 32 bit only, since -we have not yet seen the 7.1 Windows SDK with the 64 bit -compilers. <b>END WARNING.</b> +open source repositories, but this is 32 bit only. To build 64 bit +Windows binaries use the the 7.1 Windows SDK.<b>END WARNING.</b> <p> The 32-bit OpenJDK Windows build requires Microsoft Visual Studio C++ 2010 (VS2010) Professional - Edition compiler. + Edition or Express compiler. The compiler and other tools are expected to reside in the location defined by the variable <tt>VS100COMNTOOLS</tt> which @@ -1001,14 +1001,33 @@ The path <tt>/usr/bin</tt> must be after the path to the Visual Studio product. </blockquote> - <strong><a name="mssdk">Windows x64: Microsoft Visual Studio Compilers</a></strong> + <strong><a name="msvc64">Windows x64: Microsoft Visual Studio 2010 Professional Compiler</a></strong> <blockquote> - On <b>X64</b>, the set up is much the same in VS2010 + For <b>X64</b>, builds, when using the VS2010 Professional + compiler, the 64 bit build set up is much the same as 32 bit except that you run <tt>amd64\VCVARS64.BAT</tt> to set the compiler environment variables. - Previously 64 builds had used the 64 bit compiler in - an unbundled Windows SDK but this is no longer necessary. + Previously 64 bit builds had used the 64 bit compiler in + an unbundled Windows SDK but this is no longer necessary if + you have VS2010 Professional. </blockquote> + <strong><a name="mssdk64">Windows x64: Microsoft Windows 7.1 SDK 64 bit compilers.</a></strong> + For a free alternative for 64 bit builds, use the 7.1 SDK. + Microsoft say that to set up your paths for this run +<pre> + c:\Program Files\Microsoft SDKs\Windows\v7.1\bin\setenv.cmd /x64. +</pre> + What was tested is just directly setting up LIB, INCLUDE, + PATH and based on the installation directories using the + DOS short name appropriate for the system, (you will + need to set them for yours, not just blindly copy this) eg : +<pre> + set VSINSTALLDIR=c:\PROGRA~2\MICROS~1.0 + set WindowsSdkDir=c:\PROGRA~1\MICROS~1\Windows\v7.1 + set PATH=%VSINSTALLDIR%\vc\bin\amd64;%VSINSTALLDIR%\Common7\IDE;%WindowsSdkDir%\bin;%PATH% + set INCLUDE=%VSINSTALLDIR%\vc\include;%WindowsSdkDir%\include + set LIB=%VSINSTALLDIR%\vc\lib\amd64;%WindowsSdkDir%\lib\x64 +</pre> </blockquote> <!-- ------------------------------------------------------ --> <h4><a name="zip">Zip and Unzip</a></h4>
--- a/corba/.hgtags Fri Jul 30 22:43:50 2010 +0100 +++ b/corba/.hgtags Sat Jul 31 15:10:59 2010 +0100 @@ -70,3 +70,9 @@ 9718d624864c29dca44373d541e93cdd309a994f jdk7-b93 533c11186b44e3a02d6c5fe69a73260505fcfe5e jdk7-b94 06dbf406818c789bb586c1de4c002024cd26ecd2 jdk7-b95 +edc2a2659c77dabc55cb55bb617bad89e3a05bb3 jdk7-b96 +4ec9d59374caa1e5d72fa802291b4d66955a4936 jdk7-b97 +3b99409057e4c255da946f9f540d051a5ef4ab23 jdk7-b98 +95db968660e7d87c345d5cf3dc2e3db037fb7220 jdk7-b99 +a56d734a1e970e1a21a8f4feb13053e9a33674c7 jdk7-b100 +86a239832646a74811695428984b6947c0bd6dc8 jdk7-b101
--- a/corba/make/com/sun/corba/minclude/ioser_io.jmk Fri Jul 30 22:43:50 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -# -# Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. -# 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. -# - -IOSER_IO_java = \ - com/sun/corba/se/internal/io/ObjectStreamClass.java \ - com/sun/corba/se/internal/io/IIOPInputStream.java \ - com/sun/corba/se/internal/io/IIOPOutputStream.java \ - com/sun/corba/se/internal/io/LibraryManager.java -
--- a/corba/make/common/Defs-linux.gmk Fri Jul 30 22:43:50 2010 +0100 +++ b/corba/make/common/Defs-linux.gmk Sat Jul 31 15:10:59 2010 +0100 @@ -176,7 +176,16 @@ CXXFLAGS_DBG += $(CC_LOWER_OPT) endif -CPPFLAGS_COMMON = -D$(ARCH) -DARCH='"$(ARCH)"' -DLINUX $(VERSION_DEFINES) \ +CPP_ARCH_FLAGS = -DARCH='"$(ARCH)"' + +# Alpha arch does not like "alpha" defined (potential general arch cleanup issue here) +ifneq ($(ARCH),alpha) + CPP_ARCH_FLAGS += -D$(ARCH) +else + CPP_ARCH_FLAGS += -D_$(ARCH)_ +endif + +CPPFLAGS_COMMON = $(CPP_ARCH_FLAGS) -DLINUX $(VERSION_DEFINES) \ -D_LARGEFILE64_SOURCE -D_GNU_SOURCE -D_REENTRANT ifeq ($(ARCH_DATA_MODEL), 64)
--- a/corba/make/sun/corba/Makefile Fri Jul 30 22:43:50 2010 +0100 +++ b/corba/make/sun/corba/Makefile Sat Jul 31 15:10:59 2010 +0100 @@ -30,7 +30,7 @@ BUILDDIR = ../.. include $(BUILDDIR)/common/Defs.gmk -SUBDIRS = org +SUBDIRS = org core all build clean clobber:: $(SUBDIRS-loop)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/corba/make/sun/corba/core/Makefile Sat Jul 31 15:10:59 2010 +0100 @@ -0,0 +1,72 @@ +# +# Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +# +# Makefile for building RMI/IIOP +# + +BUILDDIR = ../../.. +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +# +# Files to compile. +# +CORBA_JMK_DIRECTORY=$(TOPDIR)/make/com/sun/corba/minclude/ +include $(CORBA_JMK_DIRECTORY)javax_rmi.jmk +include $(CORBA_JMK_DIRECTORY)javax_rmi_CORBA.jmk +include $(CORBA_JMK_DIRECTORY)javax_transaction.jmk +include $(CORBA_JMK_DIRECTORY)javax_activity.jmk +include $(CORBA_JMK_DIRECTORY)sun_corba.jmk + +FILES_java = \ + $(javax_rmi_java) \ + $(javax_rmi_CORBA_java) \ + $(javax_transaction_java) \ + $(javax_activity_java) \ + $(sun_corba_java) + +# +# Resources +# +LOCALE_SET_DEFINITION = jre +RESOURCE_BUNDLES_PROPERTIES = \ + com/sun/corba/se/impl/orbutil/resources/sunorb.properties + +# +# Rules +# +include $(BUILDDIR)/common/Classes.gmk + + +# +# Extra clean rules because we build more than one package. +# +clean:: classheaders.clean objects.clean + $(RM) -r $(CLASSBINDIR)/javax/rmi + $(RM) -r $(CLASSBINDIR)/javax/transaction + $(RM) -r $(CLASSBINDIR)/javax/activity + $(RM) -r $(CLASSBINDIR)/com/sun/corba/se/impl +
--- a/corba/make/sun/rmi/rmic/FILES.gmk Fri Jul 30 22:43:50 2010 +0100 +++ b/corba/make/sun/rmi/rmic/FILES.gmk Sat Jul 31 15:10:59 2010 +0100 @@ -70,7 +70,4 @@ com/sun/corba/se/internal/util/IdentityHashtable.java \ com/sun/corba/se/internal/util/Utility.java \ com/sun/corba/se/internal/util/JDKBridge.java \ - com/sun/corba/se/internal/io/LibraryManager.java \ - com/sun/corba/se/internal/io/ObjectStreamClass.java \ - com/sun/corba/se/internal/io/TypeMismatchException.java \ com/sun/corba/se/internal/util/RepositoryId.java
--- a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/CorbaResourceUtil.java Fri Jul 30 22:43:50 2010 +0100 +++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/CorbaResourceUtil.java Sat Jul 31 15:10:59 2010 +0100 @@ -75,7 +75,7 @@ args[1] = (arg1 != null ? arg1.toString() : "null"); args[2] = (arg2 != null ? arg2.toString() : "null"); - return java.text.MessageFormat.format(format, args); + return java.text.MessageFormat.format(format, (Object[]) args); } private static boolean resourcesInitialized = false;
--- a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java Fri Jul 30 22:43:50 2010 +0100 +++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java Sat Jul 31 15:10:59 2010 +0100 @@ -350,7 +350,7 @@ if (useToString) { try { - cls.getDeclaredMethod( "toString", null ) ; + cls.getDeclaredMethod( "toString", (Class[])null ) ; return true ; } catch (Exception exc) { return false ;
--- a/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/ExceptionHandlerImpl.java Fri Jul 30 22:43:50 2010 +0100 +++ b/corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/ExceptionHandlerImpl.java Sat Jul 31 15:10:59 2010 +0100 @@ -108,8 +108,8 @@ try { helperClass = Class.forName( helperName, true, loader ) ; - Method idMethod = helperClass.getDeclaredMethod( "id", null ) ; - setId( (String)idMethod.invoke( null, null ) ) ; + Method idMethod = helperClass.getDeclaredMethod( "id", (Class[])null ) ; + setId( (String)idMethod.invoke( null, (Object[])null ) ) ; } catch (Exception ex) { throw wrapper.badHelperIdMethod( ex, helperName ) ; }
--- a/corba/src/share/classes/org/omg/CORBA/ORB.java Fri Jul 30 22:43:50 2010 +0100 +++ b/corba/src/share/classes/org/omg/CORBA/ORB.java Sat Jul 31 15:10:59 2010 +0100 @@ -589,7 +589,7 @@ this.getClass().getMethod("create_operation_list", argc); // OK, the method exists, so invoke it and be happy. - Object[] argx = { oper }; + java.lang.Object[] argx = { oper }; return (org.omg.CORBA.NVList)meth.invoke(this, argx); } catch( java.lang.reflect.InvocationTargetException exs ) {
--- a/corba/src/share/classes/sun/corba/Bridge.java Fri Jul 30 22:43:50 2010 +0100 +++ b/corba/src/share/classes/sun/corba/Bridge.java Sat Jul 31 15:10:59 2010 +0100 @@ -187,7 +187,7 @@ try { // Invoke the ObjectInputStream.latestUserDefinedLoader method return (ClassLoader)latestUserDefinedLoaderMethod.invoke(null, - NO_ARGS); + (Object[])NO_ARGS); } catch (InvocationTargetException ite) { Error err = new Error( "sun.corba.Bridge.latestUserDefinedLoader: " + ite ) ;
--- a/hotspot/.hgtags Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/.hgtags Sat Jul 31 15:10:59 2010 +0100 @@ -98,3 +98,11 @@ d38f45079fe98792a7381dbb4b64f5b589ec8c58 jdk7-b94 8bfe9058ca4661779ac1d0572329f3943e68362e hs19-b01 91d861ba858daca645993a1ab6ba2fa06a8f4a5b jdk7-b95 +573e8ea5fd68e8e51eb6308d283ac3b3889d15e0 jdk7-b96 +573e8ea5fd68e8e51eb6308d283ac3b3889d15e0 hs19-b02 +5f42499e57adc16380780f40541e1a66cd601891 jdk7-b97 +8a045b3f5c13eaad92ff4baf15ca671845fcad1a jdk7-b98 +6a236384a379642b5a2398e2819db9ab4e711e9b jdk7-b99 +ad1977f08c4d69162a0775fe3f9576b9fd521d10 jdk7-b100 +6c3a919105b68c15b7db923ec9a00006e9560910 jdk7-b101 +ad1977f08c4d69162a0775fe3f9576b9fd521d10 hs19-b03
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Sat Jul 31 15:10:59 2010 +0100 @@ -35,7 +35,6 @@ public class NMethod extends CodeBlob { private static long pcDescSize; - private static CIntegerField zombieInstructionSizeField; private static sun.jvm.hotspot.types.OopField methodField; /** != InvocationEntryBci if this nmethod is an on-stack replacement method */ private static CIntegerField entryBCIField; @@ -88,7 +87,6 @@ private static void initialize(TypeDataBase db) { Type type = db.lookupType("nmethod"); - zombieInstructionSizeField = type.getCIntegerField("_zombie_instruction_size"); methodField = type.getOopField("_method"); entryBCIField = type.getCIntegerField("_entry_bci"); osrLinkField = type.getAddressField("_osr_link");
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeDisassembler.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeDisassembler.java Sat Jul 31 15:10:59 2010 +0100 @@ -72,6 +72,7 @@ addBytecodeClass(Bytecodes._invokestatic, BytecodeInvoke.class); addBytecodeClass(Bytecodes._invokespecial, BytecodeInvoke.class); addBytecodeClass(Bytecodes._invokeinterface, BytecodeInvoke.class); + addBytecodeClass(Bytecodes._invokedynamic, BytecodeInvoke.class); addBytecodeClass(Bytecodes._jsr, BytecodeJsr.class); addBytecodeClass(Bytecodes._jsr_w, BytecodeJsrW.class); addBytecodeClass(Bytecodes._iload, BytecodeLoad.class);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeInvoke.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeInvoke.java Sat Jul 31 15:10:59 2010 +0100 @@ -54,15 +54,31 @@ // returns the name of the invoked method public Symbol name() { ConstantPool cp = method().getConstants(); + if (isInvokedynamic()) { + int[] nt = cp.getNameAndTypeAt(indexForFieldOrMethod()); + return cp.getSymbolAt(nt[0]); + } return cp.getNameRefAt(index()); } // returns the signature of the invoked method public Symbol signature() { ConstantPool cp = method().getConstants(); + if (isInvokedynamic()) { + int[] nt = cp.getNameAndTypeAt(indexForFieldOrMethod()); + return cp.getSymbolAt(nt[1]); + } return cp.getSignatureRefAt(index()); } + public int getSecondaryIndex() { + if (isInvokedynamic()) { + // change byte-ordering of 4-byte integer + return VM.getVM().getBytes().swapInt(javaSignedWordAt(1)); + } + return super.getSecondaryIndex(); // throw an error + } + public Method getInvokedMethod() { return method().getConstants().getMethodRefAt(index()); } @@ -87,6 +103,7 @@ public boolean isInvokevirtual() { return adjustedInvokeCode() == Bytecodes._invokevirtual; } public boolean isInvokestatic() { return adjustedInvokeCode() == Bytecodes._invokestatic; } public boolean isInvokespecial() { return adjustedInvokeCode() == Bytecodes._invokespecial; } + public boolean isInvokedynamic() { return adjustedInvokeCode() == Bytecodes._invokedynamic; } public boolean isValid() { return isInvokeinterface() || isInvokevirtual() || @@ -104,6 +121,11 @@ buf.append(spaces); buf.append('#'); buf.append(Integer.toString(indexForFieldOrMethod())); + if (isInvokedynamic()) { + buf.append('('); + buf.append(Integer.toString(getSecondaryIndex())); + buf.append(')'); + } buf.append(" [Method "); StringBuffer sigBuf = new StringBuffer(); new SignatureConverter(signature(), sigBuf).iterateReturntype();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Sat Jul 31 15:10:59 2010 +0100 @@ -25,6 +25,7 @@ package sun.jvm.hotspot.interpreter; import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.utilities.*; public class BytecodeLoadConstant extends BytecodeWithCPIndex { @@ -32,10 +33,47 @@ super(method, bci); } + public boolean hasCacheIndex() { + // normal ldc uses CP index, but fast_aldc uses swapped CP cache index + return javaCode() != code(); + } + public int index() { - return javaCode() == Bytecodes._ldc ? + int i = javaCode() == Bytecodes._ldc ? (int) (0xFF & javaByteAt(1)) : (int) (0xFFFF & javaShortAt(1)); + if (hasCacheIndex()) { + return (0xFFFF & VM.getVM().getBytes().swapShort((short) i)); + } else { + return i; + } + } + + public int poolIndex() { + int i = index(); + if (hasCacheIndex()) { + ConstantPoolCache cpCache = method().getConstants().getCache(); + return cpCache.getEntryAt(i).getConstantPoolIndex(); + } else { + return i; + } + } + + public int cacheIndex() { + if (hasCacheIndex()) { + return index(); + } else { + return -1; // no cache index + } + } + + private Oop getCachedConstant() { + int i = cacheIndex(); + if (i >= 0) { + ConstantPoolCache cpCache = method().getConstants().getCache(); + return cpCache.getEntryAt(i).getF1(); + } + return null; } public void verify() { @@ -58,6 +96,7 @@ // has to be int or float or String or Klass return (ctag.isUnresolvedString() || ctag.isString() || ctag.isUnresolvedKlass() || ctag.isKlass() + || ctag.isMethodHandle() || ctag.isMethodType() || ctag.isInt() || ctag.isFloat())? true: false; } } @@ -112,7 +151,7 @@ public String getConstantValue() { ConstantPool cpool = method().getConstants(); - int cpIndex = index(); + int cpIndex = poolIndex(); ConstantTag ctag = cpool.getTagAt(cpIndex); if (ctag.isInt()) { return "<int " + Integer.toString(cpool.getIntAt(cpIndex)) +">"; @@ -149,6 +188,18 @@ } else { throw new RuntimeException("should not reach here"); } + } else if (ctag.isMethodHandle() || ctag.isMethodType()) { + Oop x = getCachedConstant(); + int refidx = cpool.getMethodHandleIndexAt(cpIndex); + int refkind = cpool.getMethodHandleRefKindAt(cpIndex); + return "<MethodHandle kind=" + Integer.toString(refkind) + + " ref=" + Integer.toString(refidx) + + (x == null ? "" : " @" + x.getHandle()) + ">"; + } else if (ctag.isMethodType()) { + Oop x = getCachedConstant(); + int refidx = cpool.getMethodTypeIndexAt(cpIndex); + return "<MethodType " + cpool.getSymbolAt(refidx).asString() + + (x == null ? "" : " @" + x.getHandle()) + ">"; } else { if (Assert.ASSERTS_ENABLED) { Assert.that(false, "invalid load constant type"); @@ -162,7 +213,12 @@ buf.append(getJavaBytecodeName()); buf.append(spaces); buf.append('#'); - buf.append(Integer.toString(index())); + buf.append(Integer.toString(poolIndex())); + if (hasCacheIndex()) { + buf.append('('); + buf.append(Integer.toString(cacheIndex())); + buf.append(')'); + } buf.append(spaces); buf.append(getConstantValue()); if (code() != javaCode()) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithCPIndex.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithCPIndex.java Sat Jul 31 15:10:59 2010 +0100 @@ -37,12 +37,19 @@ // the constant pool index for this bytecode public int index() { return 0xFFFF & javaShortAt(1); } + public int getSecondaryIndex() { + throw new IllegalArgumentException("must be invokedynamic"); + } + protected int indexForFieldOrMethod() { ConstantPoolCache cpCache = method().getConstants().getCache(); // get ConstantPool index from ConstantPoolCacheIndex at given bci int cpCacheIndex = index(); if (cpCache == null) { return cpCacheIndex; + } else if (code() == Bytecodes._invokedynamic) { + int secondaryIndex = getSecondaryIndex(); + return cpCache.getMainEntryAt(secondaryIndex).getConstantPoolIndex(); } else { // change byte-ordering and go via cache return cpCache.getEntryAt((int) (0xFFFF & VM.getVM().getBytes().swapShort((short) cpCacheIndex))).getConstantPoolIndex();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Sat Jul 31 15:10:59 2010 +0100 @@ -222,7 +222,7 @@ public static final int _invokespecial = 183; // 0xb7 public static final int _invokestatic = 184; // 0xb8 public static final int _invokeinterface = 185; // 0xb9 - public static final int _xxxunusedxxx = 186; // 0xba + public static final int _invokedynamic = 186; // 0xba public static final int _new = 187; // 0xbb public static final int _newarray = 188; // 0xbc public static final int _anewarray = 189; // 0xbd @@ -269,9 +269,12 @@ public static final int _fast_invokevfinal = 226; public static final int _fast_linearswitch = 227; public static final int _fast_binaryswitch = 228; - public static final int _shouldnotreachhere = 229; // For debugging + public static final int _fast_aldc = 229; + public static final int _fast_aldc_w = 230; + public static final int _return_register_finalizer = 231; + public static final int _shouldnotreachhere = 232; // For debugging - public static final int number_of_codes = 230; + public static final int number_of_codes = 233; public static int specialLengthAt(Method method, int bci) { int code = codeAt(method, bci); @@ -458,9 +461,9 @@ def(_dconst_1 , "dconst_1" , "b" , null , BasicType.getTDouble() , 2, false); def(_bipush , "bipush" , "bc" , null , BasicType.getTInt() , 1, false); def(_sipush , "sipush" , "bcc" , null , BasicType.getTInt() , 1, false); - def(_ldc , "ldc" , "bi" , null , BasicType.getTIllegal(), 1, true ); - def(_ldc_w , "ldc_w" , "bii" , null , BasicType.getTIllegal(), 1, true ); - def(_ldc2_w , "ldc2_w" , "bii" , null , BasicType.getTIllegal(), 2, true ); + def(_ldc , "ldc" , "bk" , null , BasicType.getTIllegal(), 1, true ); + def(_ldc_w , "ldc_w" , "bkk" , null , BasicType.getTIllegal(), 1, true ); + def(_ldc2_w , "ldc2_w" , "bkk" , null , BasicType.getTIllegal(), 2, true ); def(_iload , "iload" , "bi" , "wbii" , BasicType.getTInt() , 1, false); def(_lload , "lload" , "bi" , "wbii" , BasicType.getTLong() , 2, false); def(_fload , "fload" , "bi" , "wbii" , BasicType.getTFloat() , 1, false); @@ -618,26 +621,26 @@ def(_dreturn , "dreturn" , "b" , null , BasicType.getTDouble() , -2, true ); def(_areturn , "areturn" , "b" , null , BasicType.getTObject() , -1, true ); def(_return , "return" , "b" , null , BasicType.getTVoid() , 0, true ); - def(_getstatic , "getstatic" , "bjj" , null , BasicType.getTIllegal(), 1, true ); - def(_putstatic , "putstatic" , "bjj" , null , BasicType.getTIllegal(), -1, true ); - def(_getfield , "getfield" , "bjj" , null , BasicType.getTIllegal(), 0, true ); - def(_putfield , "putfield" , "bjj" , null , BasicType.getTIllegal(), -2, true ); - def(_invokevirtual , "invokevirtual" , "bjj" , null , BasicType.getTIllegal(), -1, true ); - def(_invokespecial , "invokespecial" , "bjj" , null , BasicType.getTIllegal(), -1, true ); - def(_invokestatic , "invokestatic" , "bjj" , null , BasicType.getTIllegal(), 0, true ); - def(_invokeinterface , "invokeinterface" , "bjj__", null , BasicType.getTIllegal(), -1, true ); - def(_xxxunusedxxx , "xxxunusedxxx" , null , null , BasicType.getTVoid() , 0, false); - def(_new , "new" , "bii" , null , BasicType.getTObject() , 1, true ); + def(_getstatic , "getstatic" , "bJJ" , null , BasicType.getTIllegal(), 1, true ); + def(_putstatic , "putstatic" , "bJJ" , null , BasicType.getTIllegal(), -1, true ); + def(_getfield , "getfield" , "bJJ" , null , BasicType.getTIllegal(), 0, true ); + def(_putfield , "putfield" , "bJJ" , null , BasicType.getTIllegal(), -2, true ); + def(_invokevirtual , "invokevirtual" , "bJJ" , null , BasicType.getTIllegal(), -1, true ); + def(_invokespecial , "invokespecial" , "bJJ" , null , BasicType.getTIllegal(), -1, true ); + def(_invokestatic , "invokestatic" , "bJJ" , null , BasicType.getTIllegal(), 0, true ); + def(_invokeinterface , "invokeinterface" , "bJJ__", null , BasicType.getTIllegal(), -1, true ); + def(_invokedynamic , "invokedynamic" , "bJJJJ", null , BasicType.getTIllegal(), -1, true ); + def(_new , "new" , "bkk" , null , BasicType.getTObject() , 1, true ); def(_newarray , "newarray" , "bc" , null , BasicType.getTObject() , 0, true ); - def(_anewarray , "anewarray" , "bii" , null , BasicType.getTObject() , 0, true ); + def(_anewarray , "anewarray" , "bkk" , null , BasicType.getTObject() , 0, true ); def(_arraylength , "arraylength" , "b" , null , BasicType.getTVoid() , 0, true ); def(_athrow , "athrow" , "b" , null , BasicType.getTVoid() , -1, true ); - def(_checkcast , "checkcast" , "bii" , null , BasicType.getTObject() , 0, true ); - def(_instanceof , "instanceof" , "bii" , null , BasicType.getTInt() , 0, true ); + def(_checkcast , "checkcast" , "bkk" , null , BasicType.getTObject() , 0, true ); + def(_instanceof , "instanceof" , "bkk" , null , BasicType.getTInt() , 0, true ); def(_monitorenter , "monitorenter" , "b" , null , BasicType.getTVoid() , -1, true ); def(_monitorexit , "monitorexit" , "b" , null , BasicType.getTVoid() , -1, true ); def(_wide , "wide" , "" , null , BasicType.getTVoid() , 0, false); - def(_multianewarray , "multianewarray" , "biic" , null , BasicType.getTObject() , 1, true ); + def(_multianewarray , "multianewarray" , "bkkc" , null , BasicType.getTObject() , 1, true ); def(_ifnull , "ifnull" , "boo" , null , BasicType.getTVoid() , -1, false); def(_ifnonnull , "ifnonnull" , "boo" , null , BasicType.getTVoid() , -1, false); def(_goto_w , "goto_w" , "boooo", null , BasicType.getTVoid() , 0, false); @@ -646,38 +649,44 @@ // JVM bytecodes // bytecode bytecode name format wide f. result tp stk traps std code - def(_fast_agetfield , "fast_agetfield" , "bjj" , null , BasicType.getTObject() , 0, true , _getfield ); - def(_fast_bgetfield , "fast_bgetfield" , "bjj" , null , BasicType.getTInt() , 0, true , _getfield ); - def(_fast_cgetfield , "fast_cgetfield" , "bjj" , null , BasicType.getTChar() , 0, true , _getfield ); - def(_fast_dgetfield , "fast_dgetfield" , "bjj" , null , BasicType.getTDouble() , 0, true , _getfield ); - def(_fast_fgetfield , "fast_fgetfield" , "bjj" , null , BasicType.getTFloat() , 0, true , _getfield ); - def(_fast_igetfield , "fast_igetfield" , "bjj" , null , BasicType.getTInt() , 0, true , _getfield ); - def(_fast_lgetfield , "fast_lgetfield" , "bjj" , null , BasicType.getTLong() , 0, true , _getfield ); - def(_fast_sgetfield , "fast_sgetfield" , "bjj" , null , BasicType.getTShort() , 0, true , _getfield ); + def(_fast_agetfield , "fast_agetfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _getfield ); + def(_fast_bgetfield , "fast_bgetfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _getfield ); + def(_fast_cgetfield , "fast_cgetfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _getfield ); + def(_fast_dgetfield , "fast_dgetfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _getfield ); + def(_fast_fgetfield , "fast_fgetfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _getfield ); + def(_fast_igetfield , "fast_igetfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _getfield ); + def(_fast_lgetfield , "fast_lgetfield" , "bJJ" , null , BasicType.getTLong() , 0, true , _getfield ); + def(_fast_sgetfield , "fast_sgetfield" , "bJJ" , null , BasicType.getTShort() , 0, true , _getfield ); - def(_fast_aputfield , "fast_aputfield" , "bjj" , null , BasicType.getTObject() , 0, true , _putfield ); - def(_fast_bputfield , "fast_bputfield" , "bjj" , null , BasicType.getTInt() , 0, true , _putfield ); - def(_fast_cputfield , "fast_cputfield" , "bjj" , null , BasicType.getTChar() , 0, true , _putfield ); - def(_fast_dputfield , "fast_dputfield" , "bjj" , null , BasicType.getTDouble() , 0, true , _putfield ); - def(_fast_fputfield , "fast_fputfield" , "bjj" , null , BasicType.getTFloat() , 0, true , _putfield ); - def(_fast_iputfield , "fast_iputfield" , "bjj" , null , BasicType.getTInt() , 0, true , _putfield ); - def(_fast_lputfield , "fast_lputfield" , "bjj" , null , BasicType.getTLong() , 0, true , _putfield ); - def(_fast_sputfield , "fast_sputfield" , "bjj" , null , BasicType.getTShort() , 0, true , _putfield ); + def(_fast_aputfield , "fast_aputfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _putfield ); + def(_fast_bputfield , "fast_bputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); + def(_fast_cputfield , "fast_cputfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _putfield ); + def(_fast_dputfield , "fast_dputfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _putfield ); + def(_fast_fputfield , "fast_fputfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _putfield ); + def(_fast_iputfield , "fast_iputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); + def(_fast_lputfield , "fast_lputfield" , "bJJ" , null , BasicType.getTLong() , 0, true , _putfield ); + def(_fast_sputfield , "fast_sputfield" , "bJJ" , null , BasicType.getTShort() , 0, true , _putfield ); def(_fast_aload_0 , "fast_aload_0" , "b" , null , BasicType.getTObject() , 1, true , _aload_0 ); - def(_fast_iaccess_0 , "fast_iaccess_0" , "b_jj" , null , BasicType.getTInt() , 1, true , _aload_0 ); - def(_fast_aaccess_0 , "fast_aaccess_0" , "b_jj" , null , BasicType.getTObject() , 1, true , _aload_0 ); - def(_fast_faccess_0 , "fast_faccess_0" , "b_jj" , null , BasicType.getTObject() , 1, true , _aload_0 ); + def(_fast_iaccess_0 , "fast_iaccess_0" , "b_JJ" , null , BasicType.getTInt() , 1, true , _aload_0 ); + def(_fast_aaccess_0 , "fast_aaccess_0" , "b_JJ" , null , BasicType.getTObject() , 1, true , _aload_0 ); + def(_fast_faccess_0 , "fast_faccess_0" , "b_JJ" , null , BasicType.getTObject() , 1, true , _aload_0 ); def(_fast_iload , "fast_iload" , "bi" , null , BasicType.getTInt() , 1, false, _iload); def(_fast_iload2 , "fast_iload2" , "bi_i" , null , BasicType.getTInt() , 2, false, _iload); def(_fast_icaload , "fast_icaload" , "bi_" , null , BasicType.getTInt() , 0, false, _iload); // Faster method invocation. - def(_fast_invokevfinal , "fast_invokevfinal" , "bjj" , null , BasicType.getTIllegal(), -1, true, _invokevirtual); + def(_fast_invokevfinal , "fast_invokevfinal" , "bJJ" , null , BasicType.getTIllegal(), -1, true, _invokevirtual); def(_fast_linearswitch , "fast_linearswitch" , "" , null , BasicType.getTVoid() , -1, false, _lookupswitch ); def(_fast_binaryswitch , "fast_binaryswitch" , "" , null , BasicType.getTVoid() , -1, false, _lookupswitch ); + + def(_return_register_finalizer, "return_register_finalizer", "b" , null , BasicType.getTVoid() , 0, true, _return ); + + def(_fast_aldc , "fast_aldc" , "bj" , null , BasicType.getTObject(), 1, true, _ldc ); + def(_fast_aldc_w , "fast_aldc_w" , "bJJ" , null , BasicType.getTObject(), 1, true, _ldc_w ); + def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , null , BasicType.getTVoid() , 0, false); if (Assert.ASSERTS_ENABLED) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Sat Jul 31 15:10:59 2010 +0100 @@ -152,7 +152,7 @@ return res; } - public int getNameAndTypeAt(int which) { + public int[] getNameAndTypeAt(int which) { if (Assert.ASSERTS_ENABLED) { Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool"); } @@ -160,18 +160,16 @@ if (DEBUG) { System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i); } - return i; + return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) }; } public Symbol getNameRefAt(int which) { - int refIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which)); - int nameIndex = extractLowShortFromInt(refIndex); + int nameIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[0]; return getSymbolAt(nameIndex); } public Symbol getSignatureRefAt(int which) { - int refIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which)); - int sigIndex = extractHighShortFromInt(refIndex); + int sigIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[1]; return getSymbolAt(sigIndex); } @@ -220,11 +218,11 @@ /** Lookup for entries consisting of (name_index, signature_index) */ public int getNameRefIndexAt(int index) { - int refIndex = getNameAndTypeAt(index); + int[] refIndex = getNameAndTypeAt(index); if (DEBUG) { - System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex); + System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); } - int i = extractLowShortFromInt(refIndex); + int i = refIndex[0]; if (DEBUG) { System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i); } @@ -233,17 +231,53 @@ /** Lookup for entries consisting of (name_index, signature_index) */ public int getSignatureRefIndexAt(int index) { - int refIndex = getNameAndTypeAt(index); + int[] refIndex = getNameAndTypeAt(index); if (DEBUG) { - System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex); + System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); } - int i = extractHighShortFromInt(refIndex); + int i = refIndex[1]; if (DEBUG) { System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i); } return i; } + /** Lookup for MethodHandle entries. */ + public int getMethodHandleIndexAt(int i) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); + } + int res = extractHighShortFromInt(getIntAt(i)); + if (DEBUG) { + System.err.println("ConstantPool.getMethodHandleIndexAt(" + i + "): result = " + res); + } + return res; + } + + /** Lookup for MethodHandle entries. */ + public int getMethodHandleRefKindAt(int i) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); + } + int res = extractLowShortFromInt(getIntAt(i)); + if (DEBUG) { + System.err.println("ConstantPool.getMethodHandleRefKindAt(" + i + "): result = " + res); + } + return res; + } + + /** Lookup for MethodType entries. */ + public int getMethodTypeIndexAt(int i) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(getTagAt(i).isMethodType(), "Corrupted constant pool"); + } + int res = getIntAt(i); + if (DEBUG) { + System.err.println("ConstantPool.getMethodHandleTypeAt(" + i + "): result = " + res); + } + return res; + } + final private static String[] nameForTag = new String[] { }; @@ -261,6 +295,9 @@ case JVM_CONSTANT_Methodref: return "JVM_CONSTANT_Methodref"; case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref"; case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType"; + case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle"; + case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType"; + case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic"; case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid"; case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass"; case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; @@ -317,6 +354,9 @@ case JVM_CONSTANT_Methodref: case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_NameAndType: + case JVM_CONSTANT_MethodHandle: + case JVM_CONSTANT_MethodType: + case JVM_CONSTANT_InvokeDynamic: visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); break; } @@ -467,6 +507,30 @@ + ", type = " + signatureIndex); break; } + + case JVM_CONSTANT_MethodHandle: { + dos.writeByte(cpConstType); + int value = getIntAt(ci); + short nameIndex = (short) extractLowShortFromInt(value); + short signatureIndex = (short) extractHighShortFromInt(value); + dos.writeShort(nameIndex); + dos.writeShort(signatureIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex + + ", type = " + signatureIndex); + break; + } + + case JVM_CONSTANT_InvokeDynamic: { + dos.writeByte(cpConstType); + int value = getIntAt(ci); + short bootstrapMethodIndex = (short) extractLowShortFromInt(value); + short nameAndTypeIndex = (short) extractHighShortFromInt(value); + dos.writeShort(bootstrapMethodIndex); + dos.writeShort(nameAndTypeIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bootstrapMethodIndex + + ", N&T = " + nameAndTypeIndex); + break; + } default: throw new InternalError("unknown tag: " + cpConstType); } // switch @@ -488,10 +552,12 @@ // private static int extractHighShortFromInt(int val) { + // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc. return (val >> 16) & 0xFFFF; } private static int extractLowShortFromInt(int val) { + // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc. return val & 0xFFFF; } }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Sat Jul 31 15:10:59 2010 +0100 @@ -78,6 +78,31 @@ return new ConstantPoolCacheEntry(this, i); } + public static boolean isSecondaryIndex(int i) { return (i < 0); } + public static int decodeSecondaryIndex(int i) { return isSecondaryIndex(i) ? ~i : i; } + public static int encodeSecondaryIndex(int i) { return !isSecondaryIndex(i) ? ~i : i; } + + // secondary entries hold invokedynamic call site bindings + public ConstantPoolCacheEntry getSecondaryEntryAt(int i) { + ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, decodeSecondaryIndex(i)); + if (Assert.ASSERTS_ENABLED) { + Assert.that(e.isSecondaryEntry(), "must be a secondary entry"); + } + return e; + } + + public ConstantPoolCacheEntry getMainEntryAt(int i) { + if (isSecondaryIndex(i)) { + // run through an extra level of indirection: + i = getSecondaryEntryAt(i).getMainEntryIndex(); + } + ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, i); + if (Assert.ASSERTS_ENABLED) { + Assert.that(!e.isSecondaryEntry(), "must not be a secondary entry"); + } + return e; + } + public int getIntAt(int entry, int fld) { //alignObjectSize ? long offset = baseOffset + /*alignObjectSize*/entry * elementSize + fld* getHeap().getIntSize();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheEntry.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheEntry.java Sat Jul 31 15:10:59 2010 +0100 @@ -28,6 +28,7 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; public class ConstantPoolCacheEntry { private static long size; @@ -67,9 +68,23 @@ } public int getConstantPoolIndex() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(!isSecondaryEntry(), "must not be a secondary CP entry"); + } return (int) (getIndices() & 0xFFFF); } + public boolean isSecondaryEntry() { + return (getIndices() & 0xFFFF) == 0; + } + + public int getMainEntryIndex() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isSecondaryEntry(), "must be a secondary CP entry"); + } + return (int) (getIndices() >>> 16); + } + private long getIndices() { return cp.getHandle().getCIntegerAt(indices.getOffset() + offset, indices.getSize(), indices.isUnsigned()); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Sat Jul 31 15:10:59 2010 +0100 @@ -566,6 +566,7 @@ case Bytecodes._invokespecial: case Bytecodes._invokestatic: case Bytecodes._invokeinterface: + case Bytecodes._invokedynamic: // FIXME: print signature of referenced method (need more // accessors in ConstantPool and ConstantPoolCache) int idx = currentBC.getIndexBig(); @@ -605,6 +606,7 @@ case Bytecodes._invokespecial: case Bytecodes._invokestatic: case Bytecodes._invokeinterface: + case Bytecodes._invokedynamic: // FIXME: print signature of referenced method (need more // accessors in ConstantPool and ConstantPoolCache) int idx = currentBC.getIndexBig(); @@ -1134,6 +1136,7 @@ case Bytecodes._invokespecial: case Bytecodes._invokestatic: case Bytecodes._invokeinterface: + case Bytecodes._invokedynamic: _itr_send = itr; _report_result_for_send = true; break; @@ -1379,6 +1382,7 @@ case Bytecodes._invokevirtual: case Bytecodes._invokespecial: doMethod(false, false, itr.getIndexBig(), itr.bci()); break; case Bytecodes._invokestatic: doMethod(true, false, itr.getIndexBig(), itr.bci()); break; + case Bytecodes._invokedynamic: doMethod(false, true, itr.getIndexBig(), itr.bci()); break; case Bytecodes._invokeinterface: doMethod(false, true, itr.getIndexBig(), itr.bci()); break; case Bytecodes._newarray: case Bytecodes._anewarray: ppNewRef(vCTS, itr.bci()); break; @@ -1725,7 +1729,7 @@ void doMethod (boolean is_static, boolean is_interface, int idx, int bci) { // Dig up signature for field in constant pool ConstantPool cp = _method.getConstants(); - int nameAndTypeIdx = cp.getNameAndTypeRefIndexAt(idx); + int nameAndTypeIdx = cp.getTagAt(idx).isNameAndType() ? idx : cp.getNameAndTypeRefIndexAt(idx); int signatureIdx = cp.getSignatureRefIndexAt(nameAndTypeIdx); Symbol signature = cp.getSymbolAt(signatureIdx);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Sat Jul 31 15:10:59 2010 +0100 @@ -40,6 +40,20 @@ public static final int JVM_CONSTANT_Methodref = 10; public static final int JVM_CONSTANT_InterfaceMethodref = 11; public static final int JVM_CONSTANT_NameAndType = 12; + public static final int JVM_CONSTANT_MethodHandle = 15; + public static final int JVM_CONSTANT_MethodType = 16; + public static final int JVM_CONSTANT_InvokeDynamic = 17; + + // JVM_CONSTANT_MethodHandle subtypes + public static final int JVM_REF_getField = 1; + public static final int JVM_REF_getStatic = 2; + public static final int JVM_REF_putField = 3; + public static final int JVM_REF_putStatic = 4; + public static final int JVM_REF_invokeVirtual = 5; + public static final int JVM_REF_invokeStatic = 6; + public static final int JVM_REF_invokeSpecial = 7; + public static final int JVM_REF_newInvokeSpecial = 8; + public static final int JVM_REF_invokeInterface = 9; // HotSpot specific constant pool constant types.
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java Sat Jul 31 15:10:59 2010 +0100 @@ -54,14 +54,34 @@ } - protected short getConstantPoolIndex(int bci) { + protected short getConstantPoolIndex(int rawcode, int bci) { // get ConstantPool index from ConstantPoolCacheIndex at given bci - short cpCacheIndex = method.getBytecodeShortArg(bci); + String fmt = Bytecodes.format(rawcode); + int cpCacheIndex; + switch (fmt.length()) { + case 2: cpCacheIndex = method.getBytecodeByteArg(bci); break; + case 3: cpCacheIndex = method.getBytecodeShortArg(bci); break; + case 5: + if (fmt.indexOf("__") >= 0) + cpCacheIndex = method.getBytecodeShortArg(bci); + else + cpCacheIndex = method.getBytecodeIntArg(bci); + break; + default: throw new IllegalArgumentException(); + } if (cpCache == null) { - return cpCacheIndex; + return (short) cpCacheIndex; + } else if (fmt.indexOf("JJJJ") >= 0) { + // change byte-ordering and go via secondary cache entry + return (short) cpCache.getMainEntryAt(bytes.swapInt(cpCacheIndex)).getConstantPoolIndex(); + } else if (fmt.indexOf("JJ") >= 0) { + // change byte-ordering and go via cache + return (short) cpCache.getEntryAt((int) (0xFFFF & bytes.swapShort((short)cpCacheIndex))).getConstantPoolIndex(); + } else if (fmt.indexOf("j") >= 0) { + // go via cache + return (short) cpCache.getEntryAt((int) (0xFF & cpCacheIndex)).getConstantPoolIndex(); } else { - // change byte-ordering and go via cache - return (short) cpCache.getEntryAt((int) (0xFFFF & bytes.swapShort(cpCacheIndex))).getConstantPoolIndex(); + return (short) cpCacheIndex; } } @@ -100,10 +120,31 @@ case Bytecodes._invokespecial: case Bytecodes._invokestatic: case Bytecodes._invokeinterface: { - cpoolIndex = getConstantPoolIndex(bci + 1); + cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1); writeShort(code, bci + 1, cpoolIndex); break; } + + case Bytecodes._invokedynamic: + cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1); + writeShort(code, bci + 1, cpoolIndex); + writeShort(code, bci + 3, (short)0); // clear out trailing bytes + break; + + case Bytecodes._ldc_w: + if (hotspotcode != bytecode) { + // fast_aldc_w puts constant in CP cache + cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1); + writeShort(code, bci + 1, cpoolIndex); + } + break; + case Bytecodes._ldc: + if (hotspotcode != bytecode) { + // fast_aldc puts constant in CP cache + cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1); + code[bci + 1] = (byte)(cpoolIndex); + } + break; } len = Bytecodes.lengthFor(bytecode);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Sat Jul 31 15:10:59 2010 +0100 @@ -61,10 +61,12 @@ protected short _signatureIndex; protected static int extractHighShortFromInt(int val) { + // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc. return (val >> 16) & 0xFFFF; } protected static int extractLowShortFromInt(int val) { + // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc. return val & 0xFFFF; } @@ -297,6 +299,37 @@ + ", type = " + signatureIndex); break; } + + case JVM_CONSTANT_MethodHandle: { + dos.writeByte(cpConstType); + int value = cpool.getIntAt(ci); + short bootstrapMethodIndex = (short) extractLowShortFromInt(value); + short nameAndTypeIndex = (short) extractHighShortFromInt(value); + dos.writeShort(bootstrapMethodIndex); + dos.writeShort(nameAndTypeIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + + bootstrapMethodIndex + ", N&T = " + nameAndTypeIndex); + break; + } + + case JVM_CONSTANT_MethodType: { + dos.writeByte(cpConstType); + int value = cpool.getIntAt(ci); + short refIndex = (short) value; + dos.writeShort(refIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex); + break; + } + + case JVM_CONSTANT_InvokeDynamic: { + dos.writeByte(cpConstType); + int value = cpool.getIntAt(ci); + short refIndex = (short) value; + dos.writeShort(refIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex); + break; + } + default: throw new InternalError("Unknown tag: " + cpConstType); } // switch
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Sat Jul 31 15:10:59 2010 +0100 @@ -572,6 +572,21 @@ buf.cell(Integer.toString(cpool.getIntAt(index))); break; + case JVM_CONSTANT_MethodHandle: + buf.cell("JVM_CONSTANT_MethodHandle"); + buf.cell(genLowHighShort(cpool.getIntAt(index))); + break; + + case JVM_CONSTANT_MethodType: + buf.cell("JVM_CONSTANT_MethodType"); + buf.cell(Integer.toString(cpool.getIntAt(index))); + break; + + case JVM_CONSTANT_InvokeDynamic: + buf.cell("JVM_CONSTANT_InvokeDynamic"); + buf.cell(genLowHighShort(cpool.getIntAt(index))); + break; + default: throw new InternalError("unknown tag: " + ctag); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Sat Jul 31 15:10:59 2010 +0100 @@ -38,12 +38,27 @@ private static int JVM_CONSTANT_Methodref = 10; private static int JVM_CONSTANT_InterfaceMethodref = 11; private static int JVM_CONSTANT_NameAndType = 12; + private static int JVM_CONSTANT_MethodHandle = 15; // JSR 292 + private static int JVM_CONSTANT_MethodType = 16; // JSR 292 + private static int JVM_CONSTANT_InvokeDynamic = 17; // JSR 292 private static int JVM_CONSTANT_Invalid = 0; // For bad value initialization private static int JVM_CONSTANT_UnresolvedClass = 100; // Temporary tag until actual use private static int JVM_CONSTANT_ClassIndex = 101; // Temporary tag while constructing constant pool private static int JVM_CONSTANT_UnresolvedString = 102; // Temporary tag until actual use private static int JVM_CONSTANT_StringIndex = 103; // Temporary tag while constructing constant pool private static int JVM_CONSTANT_UnresolvedClassInError = 104; // Resolution failed + private static int JVM_CONSTANT_Object = 105; // Required for BoundMethodHandle arguments. + + // JVM_CONSTANT_MethodHandle subtypes //FIXME: connect these to data structure + private static int JVM_REF_getField = 1; + private static int JVM_REF_getStatic = 2; + private static int JVM_REF_putField = 3; + private static int JVM_REF_putStatic = 4; + private static int JVM_REF_invokeVirtual = 5; + private static int JVM_REF_invokeStatic = 6; + private static int JVM_REF_invokeSpecial = 7; + private static int JVM_REF_newInvokeSpecial = 8; + private static int JVM_REF_invokeInterface = 9; private byte tag; @@ -62,6 +77,9 @@ public boolean isDouble() { return tag == JVM_CONSTANT_Double; } public boolean isNameAndType() { return tag == JVM_CONSTANT_NameAndType; } public boolean isUtf8() { return tag == JVM_CONSTANT_Utf8; } + public boolean isMethodHandle() { return tag == JVM_CONSTANT_MethodHandle; } + public boolean isMethodType() { return tag == JVM_CONSTANT_MethodType; } + public boolean isInvokeDynamic() { return tag == JVM_CONSTANT_InvokeDynamic; } public boolean isInvalid() { return tag == JVM_CONSTANT_Invalid; } @@ -73,6 +91,8 @@ public boolean isUnresolvedString() { return tag == JVM_CONSTANT_UnresolvedString; } public boolean isStringIndex() { return tag == JVM_CONSTANT_StringIndex; } + public boolean isObject() { return tag == JVM_CONSTANT_Object; } + public boolean isKlassReference() { return isKlassIndex() || isUnresolvedKlass(); } public boolean isFieldOrMethod() { return isField() || isMethod() || isInterfaceMethod(); } public boolean isSymbol() { return isUtf8(); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Sat Jul 31 15:10:59 2010 +0100 @@ -825,6 +825,8 @@ } writeln(""); disAsm.decode(new sapkg.interpreter.BytecodeVisitor() { + prologue: function(method) { }, + epilogue: function() { }, visit: function(bytecode) { if (hasLines) { var line = method.getLineNumberFromBCI(bci);
--- a/hotspot/make/hotspot_version Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/make/hotspot_version Sat Jul 31 15:10:59 2010 +0100 @@ -35,7 +35,7 @@ HS_MAJOR_VER=19 HS_MINOR_VER=0 -HS_BUILD_NUMBER=02 +HS_BUILD_NUMBER=04 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/hotspot/make/linux/makefiles/adlc.make Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/make/linux/makefiles/adlc.make Sat Jul 31 15:10:59 2010 +0100 @@ -138,7 +138,11 @@ # Normally, debugging is done directly on the ad_<arch>*.cpp files. # But -g will put #line directives in those files pointing back to <arch>.ad. +# Some builds of gcc 3.2 have a bug that gets tickled by the extra #line directives +# so skip it for 3.2 and ealier. +ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" ADLCFLAGS += -g +endif ifdef LP64 ADLCFLAGS += -D_LP64
--- a/hotspot/make/linux/makefiles/sa.make Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/make/linux/makefiles/sa.make Sat Jul 31 15:10:59 2010 +0100 @@ -40,6 +40,9 @@ # tools.jar is needed by the JDI - SA binding SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar +# TODO: if it's a modules image, check if SA module is installed. +MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules + # gnumake 3.78.1 does not accept the *s that # are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1)) @@ -65,7 +68,7 @@ echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ exit 1; \ fi - $(QUIETLY) if [ ! -f $(SA_CLASSPATH) ] ; then \ + $(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \ echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\ echo ""; \ exit 1; \
--- a/hotspot/make/solaris/makefiles/sa.make Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/make/solaris/makefiles/sa.make Sat Jul 31 15:10:59 2010 +0100 @@ -36,6 +36,9 @@ # tools.jar is needed by the JDI - SA binding SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar +# TODO: if it's a modules image, check if SA module is installed. +MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules + # gnumake 3.78.1 does not accept the *s that # are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1)) @@ -59,7 +62,7 @@ echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ exit 1; \ fi - $(QUIETLY) if [ ! -f $(SA_CLASSPATH) ] ; then \ + $(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \ echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\ echo ""; \ exit 1; \
--- a/hotspot/make/windows/makefiles/defs.make Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/make/windows/makefiles/defs.make Sat Jul 31 15:10:59 2010 +0100 @@ -32,6 +32,17 @@ PATH_SEP = ; # Need PLATFORM (os-arch combo names) for jdk and hotspot, plus libarch name +ifeq ($(ARCH_DATA_MODEL),32) + ARCH_DATA_MODEL=32 + PLATFORM=windows-i586 + VM_PLATFORM=windows_i486 + HS_ARCH=x86 + MAKE_ARGS += ARCH=x86 + MAKE_ARGS += BUILDARCH=i486 + MAKE_ARGS += Platform_arch=x86 + MAKE_ARGS += Platform_arch_model=x86_32 +endif + ifneq ($(shell $(ECHO) $(PROCESSOR_IDENTIFIER) | $(GREP) x86),) ARCH_DATA_MODEL=32 PLATFORM=windows-i586 @@ -43,43 +54,57 @@ MAKE_ARGS += Platform_arch_model=x86_32 endif -ifneq ($(shell $(ECHO) $(PROCESSOR_IDENTIFIER) | $(GREP) ia64),) - ARCH_DATA_MODEL=64 - PLATFORM=windows-ia64 - VM_PLATFORM=windows_ia64 - HS_ARCH=ia64 - MAKE_ARGS += LP64=1 - MAKE_ARGS += ARCH=ia64 - MAKE_ARGS += BUILDARCH=ia64 - MAKE_ARGS += Platform_arch=ia64 - MAKE_ARGS += Platform_arch_model=ia64 -endif +ifneq ($(ARCH_DATA_MODEL),32) + ifneq ($(shell $(ECHO) $(PROCESSOR_IDENTIFIER) | $(GREP) ia64),) + ARCH_DATA_MODEL=64 + PLATFORM=windows-ia64 + VM_PLATFORM=windows_ia64 + HS_ARCH=ia64 + MAKE_ARGS += LP64=1 + MAKE_ARGS += ARCH=ia64 + MAKE_ARGS += BUILDARCH=ia64 + MAKE_ARGS += Platform_arch=ia64 + MAKE_ARGS += Platform_arch_model=ia64 + endif # http://support.microsoft.com/kb/888731 : this can be either # AMD64 for AMD, or EM64T for Intel chips. -ifneq ($(shell $(ECHO) $(PROCESSOR_IDENTIFIER) | $(GREP) AMD64),) - ARCH_DATA_MODEL=64 - PLATFORM=windows-amd64 - VM_PLATFORM=windows_amd64 - HS_ARCH=x86 - MAKE_ARGS += LP64=1 - MAKE_ARGS += ARCH=x86 - MAKE_ARGS += BUILDARCH=amd64 - MAKE_ARGS += Platform_arch=x86 - MAKE_ARGS += Platform_arch_model=x86_64 -endif + ifneq ($(shell $(ECHO) $(PROCESSOR_IDENTIFIER) | $(GREP) AMD64),) + ARCH_DATA_MODEL=64 + PLATFORM=windows-amd64 + VM_PLATFORM=windows_amd64 + HS_ARCH=x86 + MAKE_ARGS += LP64=1 + MAKE_ARGS += ARCH=x86 + MAKE_ARGS += BUILDARCH=amd64 + MAKE_ARGS += Platform_arch=x86 + MAKE_ARGS += Platform_arch_model=x86_64 + endif + +ifneq ($(shell $(ECHO) $(PROCESSOR_IDENTIFIER) | $(GREP) EM64T),) + ARCH_DATA_MODEL=64 + PLATFORM=windows-amd64 + VM_PLATFORM=windows_amd64 + HS_ARCH=x86 + MAKE_ARGS += LP64=1 + MAKE_ARGS += ARCH=x86 + MAKE_ARGS += BUILDARCH=amd64 + MAKE_ARGS += Platform_arch=x86 + MAKE_ARGS += Platform_arch_model=x86_64 + endif # NB later OS versions than 2003 may report "Intel64" -ifneq ($(shell $(ECHO) $(PROCESSOR_IDENTIFIER) | $(GREP) "EM64T\|Intel64"),) - ARCH_DATA_MODEL=64 - PLATFORM=windows-amd64 - VM_PLATFORM=windows_amd64 - HS_ARCH=x86 - MAKE_ARGS += LP64=1 - MAKE_ARGS += ARCH=x86 - MAKE_ARGS += BUILDARCH=amd64 - MAKE_ARGS += Platform_arch=x86 - MAKE_ARGS += Platform_arch_model=x86_64 + ifneq ($(shell $(ECHO) $(PROCESSOR_IDENTIFIER) | $(GREP) Intel64),) + ARCH_DATA_MODEL=64 + PLATFORM=windows-amd64 + VM_PLATFORM=windows_amd64 + HS_ARCH=x86 + MAKE_ARGS += LP64=1 + MAKE_ARGS += ARCH=x86 + MAKE_ARGS += BUILDARCH=amd64 + MAKE_ARGS += Platform_arch=x86 + MAKE_ARGS += Platform_arch_model=x86_64 + endif endif JDK_INCLUDE_SUBDIR=win32
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -1007,9 +1007,9 @@ __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, (*NOLp)); __ delayed()->cmp(to_from, byte_count); if (NOLp == NULL) - __ brx(Assembler::greaterEqual, false, Assembler::pt, no_overlap_target); + __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, no_overlap_target); else - __ brx(Assembler::greaterEqual, false, Assembler::pt, (*NOLp)); + __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, (*NOLp)); __ delayed()->nop(); }
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -318,6 +318,31 @@ __ bind(exit); } +// Fast path for caching oop constants. +// %%% We should use this to handle Class and String constants also. +// %%% It will simplify the ldc/primitive path considerably. +void TemplateTable::fast_aldc(bool wide) { + transition(vtos, atos); + + if (!EnableMethodHandles) { + // We should not encounter this bytecode if !EnableMethodHandles. + // The verifier will stop it. However, if we get past the verifier, + // this will stop the thread in a reasonable way, without crashing the JVM. + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_IncompatibleClassChangeError)); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); + return; + } + + Register Rcache = G3_scratch; + Register Rscratch = G4_scratch; + + resolve_cache_and_index(f1_oop, Otos_i, Rcache, Rscratch, wide ? sizeof(u2) : sizeof(u1)); + + __ verify_oop(Otos_i); +} + void TemplateTable::ldc2_w() { transition(vtos, vtos); Label retry, resolved, Long, exit; @@ -1994,6 +2019,8 @@ case Bytecodes::_invokestatic : // fall through case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; + case Bytecodes::_fast_aldc : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; + case Bytecodes::_fast_aldc_w : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; default : ShouldNotReachHere(); break; } // first time invocation - must resolve first
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -375,6 +375,32 @@ __ bind(Done); } +// Fast path for caching oop constants. +// %%% We should use this to handle Class and String constants also. +// %%% It will simplify the ldc/primitive path considerably. +void TemplateTable::fast_aldc(bool wide) { + transition(vtos, atos); + + if (!EnableMethodHandles) { + // We should not encounter this bytecode if !EnableMethodHandles. + // The verifier will stop it. However, if we get past the verifier, + // this will stop the thread in a reasonable way, without crashing the JVM. + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_IncompatibleClassChangeError)); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); + return; + } + + const Register cache = rcx; + const Register index = rdx; + + resolve_cache_and_index(f1_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1)); + if (VerifyOops) { + __ verify_oop(rax); + } +} + void TemplateTable::ldc2_w() { transition(vtos, vtos); Label Long, Done; @@ -2055,6 +2081,8 @@ case Bytecodes::_invokestatic : // fall through case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; + case Bytecodes::_fast_aldc : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; + case Bytecodes::_fast_aldc_w : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; default : ShouldNotReachHere(); break; } __ movl(temp, (int)bytecode());
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -389,6 +389,32 @@ __ bind(Done); } +// Fast path for caching oop constants. +// %%% We should use this to handle Class and String constants also. +// %%% It will simplify the ldc/primitive path considerably. +void TemplateTable::fast_aldc(bool wide) { + transition(vtos, atos); + + if (!EnableMethodHandles) { + // We should not encounter this bytecode if !EnableMethodHandles. + // The verifier will stop it. However, if we get past the verifier, + // this will stop the thread in a reasonable way, without crashing the JVM. + __ call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_IncompatibleClassChangeError)); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); + return; + } + + const Register cache = rcx; + const Register index = rdx; + + resolve_cache_and_index(f1_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1)); + if (VerifyOops) { + __ verify_oop(rax); + } +} + void TemplateTable::ldc2_w() { transition(vtos, vtos); Label Long, Done; @@ -2063,6 +2089,12 @@ case Bytecodes::_invokedynamic: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; + case Bytecodes::_fast_aldc: + entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); + break; + case Bytecodes::_fast_aldc_w: + entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); + break; default: ShouldNotReachHere(); break;
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All Rights Reserved. * 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 @@ VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; static BufferBlob* stub_blob; -static const int stub_size = 300; +static const int stub_size = 400; extern "C" { typedef void (*getPsrInfo_stub_t)(void*); @@ -56,7 +56,7 @@ const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT); const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); - Label detect_486, cpu486, detect_586, std_cpuid1; + Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4; Label ext_cpuid1, ext_cpuid5, done; StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub"); @@ -131,13 +131,62 @@ __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); - __ cmpl(rax, 3); // Is cpuid(0x4) supported? - __ jccb(Assembler::belowEqual, std_cpuid1); + __ cmpl(rax, 0xa); // Is cpuid(0xB) supported? + __ jccb(Assembler::belowEqual, std_cpuid4); + + // + // cpuid(0xB) Processor Topology + // + __ movl(rax, 0xb); + __ xorl(rcx, rcx); // Threads level + __ cpuid(); + + __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB0_offset()))); + __ movl(Address(rsi, 0), rax); + __ movl(Address(rsi, 4), rbx); + __ movl(Address(rsi, 8), rcx); + __ movl(Address(rsi,12), rdx); + + __ movl(rax, 0xb); + __ movl(rcx, 1); // Cores level + __ cpuid(); + __ push(rax); + __ andl(rax, 0x1f); // Determine if valid topology level + __ orl(rax, rbx); // eax[4:0] | ebx[0:15] == 0 indicates invalid level + __ andl(rax, 0xffff); + __ pop(rax); + __ jccb(Assembler::equal, std_cpuid4); + + __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB1_offset()))); + __ movl(Address(rsi, 0), rax); + __ movl(Address(rsi, 4), rbx); + __ movl(Address(rsi, 8), rcx); + __ movl(Address(rsi,12), rdx); + + __ movl(rax, 0xb); + __ movl(rcx, 2); // Packages level + __ cpuid(); + __ push(rax); + __ andl(rax, 0x1f); // Determine if valid topology level + __ orl(rax, rbx); // eax[4:0] | ebx[0:15] == 0 indicates invalid level + __ andl(rax, 0xffff); + __ pop(rax); + __ jccb(Assembler::equal, std_cpuid4); + + __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB2_offset()))); + __ movl(Address(rsi, 0), rax); + __ movl(Address(rsi, 4), rbx); + __ movl(Address(rsi, 8), rcx); + __ movl(Address(rsi,12), rdx); // // cpuid(0x4) Deterministic cache params // + __ bind(std_cpuid4); __ movl(rax, 4); + __ cmpl(rax, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); // Is cpuid(0x4) supported? + __ jccb(Assembler::greater, std_cpuid1); + __ xorl(rcx, rcx); // L1 cache __ cpuid(); __ push(rax); @@ -460,13 +509,18 @@ AllocatePrefetchDistance = allocate_prefetch_distance(); AllocatePrefetchStyle = allocate_prefetch_style(); - if( AllocatePrefetchStyle == 2 && is_intel() && - cpu_family() == 6 && supports_sse3() ) { // watermark prefetching on Core + if( is_intel() && cpu_family() == 6 && supports_sse3() ) { + if( AllocatePrefetchStyle == 2 ) { // watermark prefetching on Core #ifdef _LP64 - AllocatePrefetchDistance = 384; + AllocatePrefetchDistance = 384; #else - AllocatePrefetchDistance = 320; + AllocatePrefetchDistance = 320; #endif + } + if( supports_sse4_2() && supports_ht() ) { // Nehalem based cpus + AllocatePrefetchDistance = 192; + AllocatePrefetchLines = 4; + } } assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,6 +114,14 @@ } bits; }; + union TplCpuidBEbx { + uint32_t value; + struct { + uint32_t logical_cpus : 16, + : 16; + } bits; + }; + union ExtCpuid1Ecx { uint32_t value; struct { @@ -211,6 +219,25 @@ uint32_t dcp_cpuid4_ecx; // unused currently uint32_t dcp_cpuid4_edx; // unused currently + // cpuid function 0xB (processor topology) + // ecx = 0 + uint32_t tpl_cpuidB0_eax; + TplCpuidBEbx tpl_cpuidB0_ebx; + uint32_t tpl_cpuidB0_ecx; // unused currently + uint32_t tpl_cpuidB0_edx; // unused currently + + // ecx = 1 + uint32_t tpl_cpuidB1_eax; + TplCpuidBEbx tpl_cpuidB1_ebx; + uint32_t tpl_cpuidB1_ecx; // unused currently + uint32_t tpl_cpuidB1_edx; // unused currently + + // ecx = 2 + uint32_t tpl_cpuidB2_eax; + TplCpuidBEbx tpl_cpuidB2_ebx; + uint32_t tpl_cpuidB2_ecx; // unused currently + uint32_t tpl_cpuidB2_edx; // unused currently + // cpuid function 0x80000000 // example, unused uint32_t ext_max_function; uint32_t ext_vendor_name_0; @@ -316,6 +343,9 @@ static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); } static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); } static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); } + static ByteSize tpl_cpuidB0_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB0_eax); } + static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); } + static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); } // Initialization static void initialize(); @@ -346,10 +376,22 @@ static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA' static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG' + static bool supports_processor_topology() { + return (_cpuid_info.std_max_function >= 0xB) && + // eax[4:0] | ebx[0:15] == 0 indicates invalid topology level. + // Some cpus have max cpuid >= 0xB but do not support processor topology. + ((_cpuid_info.tpl_cpuidB0_eax & 0x1f | _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus) != 0); + } + static uint cores_per_cpu() { uint result = 1; if (is_intel()) { - result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1); + if (supports_processor_topology()) { + result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus / + _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus; + } else { + result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1); + } } else if (is_amd()) { result = (_cpuid_info.ext_cpuid8_ecx.bits.cores_per_cpu + 1); } @@ -358,7 +400,9 @@ static uint threads_per_core() { uint result = 1; - if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) { + if (is_intel() && supports_processor_topology()) { + result = _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus; + } else if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) { result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu / cores_per_cpu(); }
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -820,7 +820,7 @@ bool is_top_frame) { assert(popframe_extra_args == 0, "what to do?"); assert(!is_top_frame || (!callee_locals && !callee_param_count), - "top frame should have no caller") + "top frame should have no caller"); // This code must exactly match what InterpreterFrame::build // does (the full InterpreterFrame::build, that is, not the
--- a/hotspot/src/os/linux/vm/os_linux.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -2079,9 +2079,9 @@ static char saved_jvm_path[MAXPATHLEN] = {0}; // Find the full path to the current module, libjvm.so or libjvm_g.so -void os::jvm_path(char *buf, jint len) { +void os::jvm_path(char *buf, jint buflen) { // Error checking. - if (len < MAXPATHLEN) { + if (buflen < MAXPATHLEN) { assert(false, "must use a large-enough buffer"); buf[0] = '\0'; return; @@ -2117,6 +2117,9 @@ // Look for JAVA_HOME in the environment. char* java_home_var = ::getenv("JAVA_HOME"); if (java_home_var != NULL && java_home_var[0] != 0) { + char* jrelib_p; + int len; + // Check the current module name "libjvm.so" or "libjvm_g.so". p = strrchr(buf, '/'); assert(strstr(p, "/libjvm") == p, "invalid library name"); @@ -2124,14 +2127,24 @@ if (realpath(java_home_var, buf) == NULL) return; - sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch); + + // determine if this is a legacy image or modules image + // modules image doesn't have "jre" subdirectory + len = strlen(buf); + jrelib_p = buf + len; + snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch); + if (0 != access(buf, F_OK)) { + snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch); + } + if (0 == access(buf, F_OK)) { // Use current module name "libjvm[_g].so" instead of // "libjvm"debug_only("_g")".so" since for fastdebug version // we should have "libjvm.so" but debug_only("_g") adds "_g"! // It is used when we are choosing the HPI library's name // "libhpi[_g].so" in hpi::initialize_get_interface(). - sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p); + len = strlen(buf); + snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p); } else { // Go back to path of .so if (realpath(dli_fname, buf) == NULL)
--- a/hotspot/src/os/linux/vm/vtune_linux.cpp Fri Jul 30 22:43:50 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. - * 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 "incls/_precompiled.incl" -#include "incls/_vtune_linux.cpp.incl" - -// empty implementation - -void VTune::start_GC() {} -void VTune::end_GC() {} -void VTune::start_class_load() {} -void VTune::end_class_load() {} -void VTune::exit() {} -void VTune::register_stub(const char* name, address start, address end) {} - -void VTune::create_nmethod(nmethod* nm) {} -void VTune::delete_nmethod(nmethod* nm) {} - -void vtune_init() {} - - -// Reconciliation History -// vtune_solaris.cpp 1.8 99/07/12 23:54:21 -// End
--- a/hotspot/src/os/solaris/vm/osThread_solaris.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/os/solaris/vm/osThread_solaris.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -123,7 +123,7 @@ int set_interrupt_callback (Sync_Interrupt_Callback * cb); void remove_interrupt_callback(Sync_Interrupt_Callback * cb); - void OSThread::do_interrupt_callbacks_at_interrupt(InterruptArguments *args); + void do_interrupt_callbacks_at_interrupt(InterruptArguments *args); // *************************************************************** // java.lang.Thread.interrupt state.
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -2435,6 +2435,8 @@ char* java_home_var = ::getenv("JAVA_HOME"); if (java_home_var != NULL && java_home_var[0] != 0) { char cpu_arch[12]; + char* jrelib_p; + int len; sysinfo(SI_ARCHITECTURE, cpu_arch, sizeof(cpu_arch)); #ifdef _LP64 // If we are on sparc running a 64-bit vm, look in jre/lib/sparcv9. @@ -2450,14 +2452,23 @@ p = strstr(p, "_g") ? "_g" : ""; realpath(java_home_var, buf); - sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch); + // determine if this is a legacy image or modules image + // modules image doesn't have "jre" subdirectory + len = strlen(buf); + jrelib_p = buf + len; + snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch); + if (0 != access(buf, F_OK)) { + snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch); + } + if (0 == access(buf, F_OK)) { // Use current module name "libjvm[_g].so" instead of // "libjvm"debug_only("_g")".so" since for fastdebug version // we should have "libjvm.so" but debug_only("_g") adds "_g"! // It is used when we are choosing the HPI library's name // "libhpi[_g].so" in hpi::initialize_get_interface(). - sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p); + len = strlen(buf); + snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p); } else { // Go back to path of .so realpath((char *)dlinfo.dli_fname, buf);
--- a/hotspot/src/os/solaris/vm/vtune_solaris.cpp Fri Jul 30 22:43:50 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * 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 "incls/_precompiled.incl" -#include "incls/_vtune_solaris.cpp.incl" - -// empty implementation - -void VTune::start_GC() {} -void VTune::end_GC() {} -void VTune::start_class_load() {} -void VTune::end_class_load() {} -void VTune::exit() {} -void VTune::register_stub(const char* name, address start, address end) {} - -void VTune::create_nmethod(nmethod* nm) {} -void VTune::delete_nmethod(nmethod* nm) {} - -void vtune_init() {}
--- a/hotspot/src/os/windows/vm/vtune_windows.cpp Fri Jul 30 22:43:50 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,290 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * 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 "incls/_precompiled.incl" -#include "incls/_vtune_windows.cpp.incl" - -static int current_method_ID = 0; - -// ------------- iJITProf.h ------------------- -// defined by Intel -- do not change - -#include "windows.h" - -extern "C" { - enum iJITP_Event { - ExceptionOccurred_S, // Java exception - ExceptionOccurred_IDS, - - Shutdown, // VM exit - - ThreadCreate, // threads - ThreadDestroy, - ThreadSwitch, - - ClassLoadStart, // class loading - ClassLoadEnd, - - GCStart, // GC - GCEnd, - - NMethodCreate = 13, // nmethod creation - NMethodDelete - - // rest of event types omitted (call profiling not supported yet) - }; - - // version number -- 0 if VTune not installed - int WINAPI iJitP_VersionNumber(); - - enum iJITP_ModeFlags { - NoNotification = 0x0, // don't call vtune - NotifyNMethodCreate = 0x1, // notify NMethod_Create - NotifyNMethodDelete = 0x2, // notify NMethod_Create - NotifyMethodEnter = 0x4, // method entry - NotifyMethodExit = 0x8, // method exit - NotifyShutdown = 0x10, // VM exit - NotifyGC = 0x20, // GC - }; - - // call back function type - typedef void (WINAPI *ModeChangedFn)(iJITP_ModeFlags flags); - - // ------------- VTune method interfaces ---------------------- - typedef void (WINAPI *RegisterCallbackFn)(ModeChangedFn fn); // register callback - typedef int (WINAPI *NotifyEventFn)(iJITP_Event, void* event_data); - - // specific event data structures - - // data for NMethodCreate - - struct VTuneObj { // base class for allocation - // (can't use CHeapObj -- has vtable ptr) - void* operator new(size_t size) { return os::malloc(size); } - void operator delete(void* p) { fatal("never delete VTune data"); } - }; - - struct LineNumberInfo : VTuneObj { // PC-to-line number mapping - unsigned long offset; // byte offset from start of method - unsigned long line_num; // corresponding line number - }; - - struct MethodLoadInfo : VTuneObj { - unsigned long methodID; // unique method ID - const char* name; // method name - unsigned long instr_start; // start address - unsigned long instr_size; // length in bytes - unsigned long line_number_size; // size of line number table - LineNumberInfo* line_number_table; // line number mapping - unsigned long classID; // unique class ID - char* class_file_name; // fully qualified class file name - char* source_file_name; // fully qualified source file name - - MethodLoadInfo(nmethod* nm); // for real nmethods - MethodLoadInfo(const char* vm_name, address start, address end); - // for "nmethods" like stubs, interpreter, etc - - }; - - // data for NMethodDelete - struct MethodInfo : VTuneObj { - unsigned long methodID; // unique method ID - unsigned long classID; // (added for convenience -- not part of Intel interface) - - MethodInfo(methodOop m); - }; -}; - -MethodInfo::MethodInfo(methodOop m) { - // just give it a new ID -- we're not compiling methods twice (usually) - // (and even if we did, one might want to see the two versions separately) - methodID = ++current_method_ID; -} - -MethodLoadInfo::MethodLoadInfo(const char* vm_name, address start, address end) { - classID = 0; - methodID = ++current_method_ID; - name = vm_name; - instr_start = (unsigned long)start; - instr_size = end - start; - line_number_size = 0; - line_number_table = NULL; - class_file_name = source_file_name = "HotSpot JVM"; -} - -MethodLoadInfo::MethodLoadInfo(nmethod* nm) { - methodOop m = nm->method(); - MethodInfo info(m); - classID = info.classID; - methodID = info.methodID; - name = strdup(m->name()->as_C_string()); - instr_start = (unsigned long)nm->instructions_begin(); - instr_size = nm->code_size(); - line_number_size = 0; - line_number_table = NULL; - klassOop kl = m->method_holder(); - char* class_name = Klass::cast(kl)->name()->as_C_string(); - char* file_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + 1); - strcpy(file_name, class_name); - class_file_name = file_name; - char* src_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + strlen(".java") + 1); - strcpy(src_name, class_name); - strcat(src_name, ".java"); - source_file_name = src_name; -} - -// --------------------- DLL loading functions ------------------------ - -#define DLLNAME "iJitProf.dll" - -static HINSTANCE load_lib(char* name) { - HINSTANCE lib = NULL; - HKEY hk; - - // try to get VTune directory from the registry - if (RegOpenKey(HKEY_CURRENT_USER, "Software\\VB and VBA Program Settings\\VTune\\StartUp", &hk) == ERROR_SUCCESS) { - for (int i = 0; true; i++) { - char szName[MAX_PATH + 1]; - char szVal [MAX_PATH + 1]; - DWORD cbName, cbVal; - - cbName = cbVal = MAX_PATH + 1; - if (RegEnumValue(hk, i, szName, &cbName, NULL, NULL, (LPBYTE)szVal, &cbVal) == ERROR_SUCCESS) { - // get VTune directory - if (!strcmp(szName, name)) { - char*p = szVal; - while (*p == ' ') p++; // trim - char* q = p + strlen(p) - 1; - while (*q == ' ') *(q--) = '\0'; - - // chdir to the VTune dir - GetCurrentDirectory(MAX_PATH + 1, szName); - SetCurrentDirectory(p); - // load lib - lib = LoadLibrary(strcat(strcat(p, "\\"), DLLNAME)); - if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s", p); - // restore current dir - SetCurrentDirectory(szName); - break; - } - } else { - break; - } - } - } - return lib; -} - -static RegisterCallbackFn iJIT_RegisterCallback = NULL; -static NotifyEventFn iJIT_NotifyEvent = NULL; - -static bool load_iJIT_funcs() { - // first try to load from PATH - HINSTANCE lib = LoadLibrary(DLLNAME); - if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s via PATH", DLLNAME); - - // if not successful, try to look in the VTUNE directory - if (lib == NULL) lib = load_lib("VTUNEDIR30"); - if (lib == NULL) lib = load_lib("VTUNEDIR25"); - if (lib == NULL) lib = load_lib("VTUNEDIR"); - - if (lib == NULL) return false; // unsuccessful - - // try to load the functions - iJIT_RegisterCallback = (RegisterCallbackFn)GetProcAddress(lib, "iJIT_RegisterCallback"); - iJIT_NotifyEvent = (NotifyEventFn) GetProcAddress(lib, "iJIT_NotifyEvent"); - - if (!iJIT_RegisterCallback) tty->print_cr("*couldn't find VTune entry point iJIT_RegisterCallback"); - if (!iJIT_NotifyEvent) tty->print_cr("*couldn't find VTune entry point iJIT_NotifyEvent"); - return iJIT_RegisterCallback != NULL && iJIT_NotifyEvent != NULL; -} - -// --------------------- VTune class ------------------------ - -static bool active = false; -static int flags = 0; - -void VTune::start_GC() { - if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCStart, NULL); -} - -void VTune::end_GC() { - if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCEnd, NULL); -} - -void VTune::start_class_load() { - // not yet implemented in VTune -} - -void VTune::end_class_load() { - // not yet implemented in VTune -} - -void VTune::exit() { - if (active && (flags & NotifyShutdown)) iJIT_NotifyEvent(Shutdown, NULL); -} - -void VTune::register_stub(const char* name, address start, address end) { - if (flags & NotifyNMethodCreate) { - MethodLoadInfo* info = new MethodLoadInfo(name, start, end); - if (PrintMiscellaneous && WizardMode && Verbose) { - tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID, - info->instr_start, info->instr_start + info->instr_size); - } - iJIT_NotifyEvent(NMethodCreate, info); - } -} - -void VTune::create_nmethod(nmethod* nm) { - if (flags & NotifyNMethodCreate) { - MethodLoadInfo* info = new MethodLoadInfo(nm); - if (PrintMiscellaneous && WizardMode && Verbose) { - tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID, - info->instr_start, info->instr_start + info->instr_size); - } - iJIT_NotifyEvent(NMethodCreate, info); - } -} - -void VTune::delete_nmethod(nmethod* nm) { - if (flags & NotifyNMethodDelete) { - MethodInfo* info = new MethodInfo(nm->method()); - iJIT_NotifyEvent(NMethodDelete, info); - } -} - -static void set_flags(int new_flags) { - flags = new_flags; - // if (WizardMode) tty->print_cr("*new VTune flags: %#x", flags); -} - -void vtune_init() { - if (!UseVTune) return; - active = load_iJIT_funcs(); - if (active) { - iJIT_RegisterCallback((ModeChangedFn)set_flags); - } else { - assert(flags == 0, "flags shouldn't be set"); - } -}
--- a/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -26,7 +26,7 @@ #ifdef AMD64 (void)memmove(to, from, count * HeapWordSize); #else - // Same as pd_aligned_conjoint_words, except includes a zero-count check. + // Includes a zero-count check. intx temp; __asm__ volatile(" testl %6,%6 ;" " jz 7f ;" @@ -84,7 +84,7 @@ break; } #else - // Same as pd_aligned_disjoint_words, except includes a zero-count check. + // Includes a zero-count check. intx temp; __asm__ volatile(" testl %6,%6 ;" " jz 3f ;" @@ -130,75 +130,18 @@ } static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 - (void)memmove(to, from, count * HeapWordSize); -#else - // Same as pd_conjoint_words, except no zero-count check. - intx temp; - __asm__ volatile(" cmpl %4,%5 ;" - " leal -4(%4,%6,4),%3;" - " jbe 1f ;" - " cmpl %7,%5 ;" - " jbe 4f ;" - "1: cmpl $32,%6 ;" - " ja 3f ;" - " subl %4,%1 ;" - "2: movl (%4),%3 ;" - " movl %7,(%5,%4,1) ;" - " addl $4,%0 ;" - " subl $1,%2 ;" - " jnz 2b ;" - " jmp 7f ;" - "3: rep; smovl ;" - " jmp 7f ;" - "4: cmpl $32,%2 ;" - " movl %7,%0 ;" - " leal -4(%5,%6,4),%1;" - " ja 6f ;" - " subl %4,%1 ;" - "5: movl (%4),%3 ;" - " movl %7,(%5,%4,1) ;" - " subl $4,%0 ;" - " subl $1,%2 ;" - " jnz 5b ;" - " jmp 7f ;" - "6: std ;" - " rep; smovl ;" - " cld ;" - "7: nop " - : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) - : "0" (from), "1" (to), "2" (count), "3" (temp) - : "memory", "flags"); -#endif // AMD64 + pd_conjoint_words(from, to, count); } static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { -#ifdef AMD64 pd_disjoint_words(from, to, count); -#else - // Same as pd_disjoint_words, except no zero-count check. - intx temp; - __asm__ volatile(" cmpl $32,%6 ;" - " ja 2f ;" - " subl %4,%1 ;" - "1: movl (%4),%3 ;" - " movl %7,(%5,%4,1);" - " addl $4,%0 ;" - " subl $1,%2 ;" - " jnz 1b ;" - " jmp 3f ;" - "2: rep; smovl ;" - "3: nop " - : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) - : "0" (from), "1" (to), "2" (count), "3" (temp) - : "memory", "cc"); -#endif // AMD64 } static void pd_conjoint_bytes(void* from, void* to, size_t count) { #ifdef AMD64 (void)memmove(to, from, count); #else + // Includes a zero-count check. intx temp; __asm__ volatile(" testl %6,%6 ;" " jz 13f ;"
--- a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s Sat Jul 31 15:10:59 2010 +0100 @@ -121,10 +121,10 @@ jnz 3b addl %esi,%edi 4: movl %eax,%ecx # byte count less prefix - andl $3,%ecx # suffix byte count +5: andl $3,%ecx # suffix byte count jz 7f # no suffix # copy suffix -5: xorl %eax,%eax + xorl %eax,%eax 6: movb (%esi,%eax,1),%dl movb %dl,(%edi,%eax,1) addl $1,%eax @@ -159,10 +159,10 @@ # copy dwords, aligned or not 3: rep; smovl 4: movl %eax,%ecx # byte count - andl $3,%ecx # suffix byte count +5: andl $3,%ecx # suffix byte count jz 7f # no suffix # copy suffix -5: subl %esi,%edi + subl %esi,%edi addl $3,%esi 6: movb (%esi),%dl movb %dl,(%edi,%esi,1) @@ -214,10 +214,10 @@ # copy aligned dwords 3: rep; smovl 4: movl %eax,%ecx - andl $3,%ecx +5: andl $3,%ecx jz 7f # copy suffix -5: xorl %eax,%eax + xorl %eax,%eax 6: movb (%esi,%eax,1),%dl movb %dl,(%edi,%eax,1) addl $1,%eax @@ -250,9 +250,9 @@ jnz 3b addl %esi,%edi 4: movl %eax,%ecx - andl $3,%ecx +5: andl $3,%ecx jz 7f -5: subl %esi,%edi + subl %esi,%edi addl $3,%esi 6: movb (%esi),%dl movb %dl,(%edi,%esi,1) @@ -287,11 +287,12 @@ andl $3,%eax # either 0 or 2 jz 1f # no prefix # copy prefix + subl $1,%ecx + jl 5f # zero count movw (%esi),%dx movw %dx,(%edi) addl %eax,%esi # %eax == 2 addl %eax,%edi - subl $1,%ecx 1: movl %ecx,%eax # word count less prefix sarl %ecx # dword count jz 4f # no dwords to move @@ -454,12 +455,13 @@ ret .=.+10 2: subl %esi,%edi + jmp 4f .p2align 4,,15 3: movl (%esi),%edx movl %edx,(%edi,%esi,1) addl $4,%esi - subl $1,%ecx - jnz 3b +4: subl $1,%ecx + jge 3b popl %edi popl %esi ret @@ -467,19 +469,20 @@ std leal -4(%edi,%ecx,4),%edi # to + count*4 - 4 cmpl $32,%ecx - ja 3f # > 32 dwords + ja 4f # > 32 dwords subl %eax,%edi # eax == from + count*4 - 4 + jmp 3f .p2align 4,,15 2: movl (%eax),%edx movl %edx,(%edi,%eax,1) subl $4,%eax - subl $1,%ecx - jnz 2b +3: subl $1,%ecx + jge 2b cld popl %edi popl %esi ret -3: movl %eax,%esi # from + count*4 - 4 +4: movl %eax,%esi # from + count*4 - 4 rep; smovl cld popl %edi
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -861,7 +861,7 @@ cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; -extern "C" _solaris_raw_setup_fpu(address ptr); +extern "C" void _solaris_raw_setup_fpu(address ptr); void os::setup_fpu() { address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std(); _solaris_raw_setup_fpu(fpu_cntrl);
--- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.s Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.s Sat Jul 31 15:10:59 2010 +0100 @@ -154,10 +154,10 @@ jnz 3b addl %esi,%edi 4: movl %eax,%ecx / byte count less prefix - andl $3,%ecx / suffix byte count +5: andl $3,%ecx / suffix byte count jz 7f / no suffix / copy suffix -5: xorl %eax,%eax + xorl %eax,%eax 6: movb (%esi,%eax,1),%dl movb %dl,(%edi,%eax,1) addl $1,%eax @@ -192,10 +192,10 @@ / copy dwords, aligned or not 3: rep; smovl 4: movl %eax,%ecx / byte count - andl $3,%ecx / suffix byte count +5: andl $3,%ecx / suffix byte count jz 7f / no suffix / copy suffix -5: subl %esi,%edi + subl %esi,%edi addl $3,%esi 6: movb (%esi),%dl movb %dl,(%edi,%esi,1) @@ -246,10 +246,10 @@ / copy aligned dwords 3: rep; smovl 4: movl %eax,%ecx - andl $3,%ecx +5: andl $3,%ecx jz 7f / copy suffix -5: xorl %eax,%eax + xorl %eax,%eax 6: movb (%esi,%eax,1),%dl movb %dl,(%edi,%eax,1) addl $1,%eax @@ -282,9 +282,9 @@ jnz 3b addl %esi,%edi 4: movl %eax,%ecx - andl $3,%ecx +5: andl $3,%ecx jz 7f -5: subl %esi,%edi + subl %esi,%edi addl $3,%esi 6: movb (%esi),%dl movb %dl,(%edi,%esi,1) @@ -318,11 +318,12 @@ andl $3,%eax / either 0 or 2 jz 1f / no prefix / copy prefix + subl $1,%ecx + jl 5f / zero count movw (%esi),%dx movw %dx,(%edi) addl %eax,%esi / %eax == 2 addl %eax,%edi - subl $1,%ecx 1: movl %ecx,%eax / word count less prefix sarl %ecx / dword count jz 4f / no dwords to move @@ -482,12 +483,13 @@ ret .=.+10 2: subl %esi,%edi + jmp 4f .align 16 3: movl (%esi),%edx movl %edx,(%edi,%esi,1) addl $4,%esi - subl $1,%ecx - jnz 3b +4: subl $1,%ecx + jge 3b popl %edi popl %esi ret @@ -495,19 +497,20 @@ std leal -4(%edi,%ecx,4),%edi / to + count*4 - 4 cmpl $32,%ecx - ja 3f / > 32 dwords + ja 4f / > 32 dwords subl %eax,%edi / eax == from + count*4 - 4 + jmp 3f .align 16 2: movl (%eax),%edx movl %edx,(%edi,%eax,1) subl $4,%eax - subl $1,%ecx - jnz 2b +3: subl $1,%ecx + jge 2b cld popl %edi popl %esi ret -3: movl %eax,%esi / from + count*4 - 4 +4: movl %eax,%esi / from + count*4 - 4 rep; smovl cld popl %edi
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -404,7 +404,7 @@ locs_start = REALLOC_RESOURCE_ARRAY(relocInfo, _locs_start, old_capacity, new_capacity); } else { locs_start = NEW_RESOURCE_ARRAY(relocInfo, new_capacity); - Copy::conjoint_bytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo)); + Copy::conjoint_jbytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo)); _locs_own = true; } _locs_start = locs_start; @@ -581,7 +581,7 @@ (HeapWord*)(buf+buf_offset), (lsize + HeapWordSize-1) / HeapWordSize); } else { - Copy::conjoint_bytes(lstart, buf+buf_offset, lsize); + Copy::conjoint_jbytes(lstart, buf+buf_offset, lsize); } } buf_offset += lsize;
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -242,10 +242,10 @@ code->insts()->initialize_shared_locs((relocInfo*)locs_buffer, locs_buffer_size / sizeof(relocInfo)); code->initialize_consts_size(Compilation::desired_max_constant_size()); - // Call stubs + deopt/exception handler + // Call stubs + two deopt handlers (regular and MH) + exception handler code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) + LIR_Assembler::exception_handler_size + - LIR_Assembler::deopt_handler_size); + 2 * LIR_Assembler::deopt_handler_size); }
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -878,15 +878,12 @@ case T_OBJECT : { ciObject* obj = con.as_object(); - if (obj->is_klass()) { - ciKlass* klass = obj->as_klass(); - if (!klass->is_loaded() || PatchALot) { - patch_state = state()->copy(); - t = new ObjectConstant(obj); - } else { - t = new InstanceConstant(klass->java_mirror()); - } + if (!obj->is_loaded() + || (PatchALot && obj->klass() != ciEnv::current()->String_klass())) { + patch_state = state()->copy(); + t = new ObjectConstant(obj); } else { + assert(!obj->is_klass(), "must be java_mirror of klass"); t = new InstanceConstant(obj->as_instance()); } break;
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -601,7 +601,7 @@ static klassOop resolve_field_return_klass(methodHandle caller, int bci, TRAPS) { - Bytecode_field* field_access = Bytecode_field_at(caller(), caller->bcp_from(bci)); + Bytecode_field* field_access = Bytecode_field_at(caller, bci); // This can be static or non-static field access Bytecodes::Code code = field_access->code(); @@ -721,7 +721,7 @@ Handle load_klass(THREAD, NULL); // oop needed by load_klass_patching code if (stub_id == Runtime1::access_field_patching_id) { - Bytecode_field* field_access = Bytecode_field_at(caller_method(), caller_method->bcp_from(bci)); + Bytecode_field* field_access = Bytecode_field_at(caller_method, bci); FieldAccessInfo result; // initialize class if needed Bytecodes::Code code = field_access->code(); constantPoolHandle constants(THREAD, caller_method->constants()); @@ -781,11 +781,9 @@ case Bytecodes::_ldc: case Bytecodes::_ldc_w: { - Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method(), - caller_method->bcp_from(bci)); - klassOop resolved = caller_method->constants()->klass_at(cc->index(), CHECK); - // ldc wants the java mirror. - k = resolved->klass_part()->java_mirror(); + Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method, bci); + k = cc->resolve_constant(CHECK); + assert(k != NULL && !k->is_klass(), "must be class mirror or other Java constant"); } break; default: Unimplemented(); @@ -816,6 +814,15 @@ // Return to the now deoptimized frame. } + // If we are patching in a non-perm oop, make sure the nmethod + // is on the right list. + if (ScavengeRootsInCode && load_klass.not_null() && load_klass->is_scavengable()) { + MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag); + nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); + guarantee(nm != NULL, "only nmethods can contain non-perm oops"); + if (!nm->on_scavenge_root_list()) + CodeCache::add_scavenge_root_nmethod(nm); + } // Now copy code back @@ -1115,7 +1122,7 @@ if (length == 0) return; // Not guaranteed to be word atomic, but that doesn't matter // for anything but an oop array, which is covered by oop_arraycopy. - Copy::conjoint_bytes(src, dst, length); + Copy::conjoint_jbytes(src, dst, length); JRT_END JRT_LEAF(void, Runtime1::oop_arraycopy(HeapWord* src, HeapWord* dst, int num))
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -106,7 +106,7 @@ void BCEscapeAnalyzer::set_returned(ArgumentMap vars) { for (int i = 0; i < _arg_size; i++) { if (vars.contains(i)) - _arg_returned.set_bit(i); + _arg_returned.set(i); } _return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated()); _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars()); @@ -126,16 +126,16 @@ if (_conservative) return true; for (int i = 0; i < _arg_size; i++) { - if (vars.contains(i) && _arg_stack.at(i)) + if (vars.contains(i) && _arg_stack.test(i)) return true; } return false; } -void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) { +void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) { for (int i = 0; i < _arg_size; i++) { if (vars.contains(i)) { - bm.clear_bit(i); + bm >>= i; } } } @@ -1157,15 +1157,15 @@ ciSignature* sig = method()->signature(); int j = 0; if (!method()->is_static()) { - _arg_local.set_bit(0); - _arg_stack.set_bit(0); + _arg_local.set(0); + _arg_stack.set(0); j++; } for (i = 0; i < sig->count(); i++) { ciType* t = sig->type_at(i); if (!t->is_primitive_type()) { - _arg_local.set_bit(j); - _arg_stack.set_bit(j); + _arg_local.set(j); + _arg_stack.set(j); } j += t->size(); } @@ -1198,9 +1198,9 @@ set_modified(var, OFFSET_ANY, 4); set_global_escape(var); } - _arg_local.clear(); - _arg_stack.clear(); - _arg_returned.clear(); + _arg_local.Clear(); + _arg_stack.Clear(); + _arg_returned.Clear(); _return_local = false; _return_allocated = false; _allocated_escapes = true; @@ -1254,7 +1254,7 @@ // Do not scan method if it has no object parameters and // does not returns an object (_return_allocated is set in initialize()). - if (_arg_local.is_empty() && !_return_allocated) { + if (_arg_local.Size() == 0 && !_return_allocated) { // Clear all info since method's bytecode was not analysed and // set pessimistic escape information. clear_escape_info(); @@ -1275,14 +1275,14 @@ // if (!has_dependencies() && !methodData()->is_empty()) { for (i = 0; i < _arg_size; i++) { - if (_arg_local.at(i)) { - assert(_arg_stack.at(i), "inconsistent escape info"); + if (_arg_local.test(i)) { + assert(_arg_stack.test(i), "inconsistent escape info"); methodData()->set_arg_local(i); methodData()->set_arg_stack(i); - } else if (_arg_stack.at(i)) { + } else if (_arg_stack.test(i)) { methodData()->set_arg_stack(i); } - if (_arg_returned.at(i)) { + if (_arg_returned.test(i)) { methodData()->set_arg_returned(i); } methodData()->set_arg_modified(i, _arg_modified[i]); @@ -1308,9 +1308,12 @@ // read escape information from method descriptor for (int i = 0; i < _arg_size; i++) { - _arg_local.at_put(i, methodData()->is_arg_local(i)); - _arg_stack.at_put(i, methodData()->is_arg_stack(i)); - _arg_returned.at_put(i, methodData()->is_arg_returned(i)); + if (methodData()->is_arg_local(i)) + _arg_local.set(i); + if (methodData()->is_arg_stack(i)) + _arg_stack.set(i); + if (methodData()->is_arg_returned(i)) + _arg_returned.set(i); _arg_modified[i] = methodData()->arg_modified(i); } _return_local = methodData()->eflag_set(methodDataOopDesc::return_local); @@ -1358,26 +1361,26 @@ BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent) : _conservative(method == NULL || !EstimateArgEscape) + , _arena(CURRENT_ENV->arena()) , _method(method) , _methodData(method ? method->method_data() : NULL) , _arg_size(method ? method->arg_size() : 0) - , _stack() - , _arg_local(_arg_size) - , _arg_stack(_arg_size) - , _arg_returned(_arg_size) - , _dirty(_arg_size) + , _arg_local(_arena) + , _arg_stack(_arena) + , _arg_returned(_arena) + , _dirty(_arena) , _return_local(false) , _return_allocated(false) , _allocated_escapes(false) , _unknown_modified(false) - , _dependencies() + , _dependencies(_arena, 4, 0, NULL) , _parent(parent) , _level(parent == NULL ? 0 : parent->level() + 1) { if (!_conservative) { - _arg_local.clear(); - _arg_stack.clear(); - _arg_returned.clear(); - _dirty.clear(); + _arg_local.Clear(); + _arg_stack.Clear(); + _arg_returned.Clear(); + _dirty.Clear(); Arena* arena = CURRENT_ENV->arena(); _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint)); Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint)); @@ -1414,8 +1417,8 @@ deps->assert_evol_method(method()); } for (int i = 0; i < _dependencies.length(); i+=2) { - ciKlass *k = _dependencies[i]->as_klass(); - ciMethod *m = _dependencies[i+1]->as_method(); + ciKlass *k = _dependencies.at(i)->as_klass(); + ciMethod *m = _dependencies.at(i+1)->as_method(); deps->assert_unique_concrete_method(k, m); } }
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -22,9 +22,6 @@ * */ -define_array(ciObjectArray, ciObject*); -define_stack(ciObjectList, ciObjectArray); - // This class implements a fast, conservative analysis of effect of methods // on the escape state of their arguments. The analysis is at the bytecode // level. @@ -34,18 +31,17 @@ class BCEscapeAnalyzer : public ResourceObj { private: + Arena* _arena; // ciEnv arena + bool _conservative; // If true, return maximally // conservative results. ciMethod* _method; ciMethodData* _methodData; int _arg_size; - - intStack _stack; - - BitMap _arg_local; - BitMap _arg_stack; - BitMap _arg_returned; - BitMap _dirty; + VectorSet _arg_local; + VectorSet _arg_stack; + VectorSet _arg_returned; + VectorSet _dirty; enum{ ARG_OFFSET_MAX = 31}; uint *_arg_modified; @@ -54,7 +50,7 @@ bool _allocated_escapes; bool _unknown_modified; - ciObjectList _dependencies; + GrowableArray<ciObject *> _dependencies; ciMethodBlocks *_methodBlocks; @@ -68,20 +64,10 @@ private: // helper functions bool is_argument(int i) { return i >= 0 && i < _arg_size; } - - void raw_push(int i) { _stack.push(i); } - int raw_pop() { return _stack.is_empty() ? -1 : _stack.pop(); } - void apush(int i) { raw_push(i); } - void spush() { raw_push(-1); } - void lpush() { spush(); spush(); } - int apop() { return raw_pop(); } - void spop() { assert(_stack.is_empty() || _stack.top() == -1, ""); raw_pop(); } - void lpop() { spop(); spop(); } - void set_returned(ArgumentMap vars); bool is_argument(ArgumentMap vars); bool is_arg_stack(ArgumentMap vars); - void clear_bits(ArgumentMap vars, BitMap &bs); + void clear_bits(ArgumentMap vars, VectorSet &bs); void set_method_escape(ArgumentMap vars); void set_global_escape(ArgumentMap vars); void set_dirty(ArgumentMap vars); @@ -116,25 +102,25 @@ ciMethodData* methodData() const { return _methodData; } BCEscapeAnalyzer* parent() const { return _parent; } int level() const { return _level; } - ciObjectList* dependencies() { return &_dependencies; } + GrowableArray<ciObject *>* dependencies() { return &_dependencies; } bool has_dependencies() const { return !_dependencies.is_empty(); } // retrieval of interprocedural escape information // The given argument does not escape the callee. bool is_arg_local(int i) const { - return !_conservative && _arg_local.at(i); + return !_conservative && _arg_local.test(i); } // The given argument escapes the callee, but does not become globally // reachable. bool is_arg_stack(int i) const { - return !_conservative && _arg_stack.at(i); + return !_conservative && _arg_stack.test(i); } // The given argument does not escape globally, and may be returned. bool is_arg_returned(int i) const { - return !_conservative && _arg_returned.at(i); } + return !_conservative && _arg_returned.test(i); } // True iff only input arguments are returned. bool is_return_local() const {
--- a/hotspot/src/share/vm/ci/ciCPCache.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciCPCache.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -44,13 +44,23 @@ // ciCPCache::is_f1_null_at bool ciCPCache::is_f1_null_at(int index) { VM_ENTRY_MARK; - constantPoolCacheOop cpcache = (constantPoolCacheOop) get_oop(); - oop f1 = cpcache->secondary_entry_at(index)->f1(); + oop f1 = entry_at(index)->f1(); return (f1 == NULL); } // ------------------------------------------------------------------ +// ciCPCache::get_pool_index +int ciCPCache::get_pool_index(int index) { + VM_ENTRY_MARK; + ConstantPoolCacheEntry* e = entry_at(index); + if (e->is_secondary_entry()) + e = entry_at(e->main_entry_index()); + return e->constant_pool_index(); +} + + +// ------------------------------------------------------------------ // ciCPCache::print // // Print debugging information about the cache.
--- a/hotspot/src/share/vm/ci/ciCPCache.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciCPCache.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -29,6 +29,18 @@ // Note: This class is called ciCPCache as ciConstantPoolCache is used // for something different. class ciCPCache : public ciObject { +private: + constantPoolCacheOop get_cpCacheOop() { // must be called inside a VM_ENTRY_MARK + return (constantPoolCacheOop) get_oop(); + } + + ConstantPoolCacheEntry* entry_at(int i) { + int raw_index = i; + if (constantPoolCacheOopDesc::is_secondary_index(i)) + raw_index = constantPoolCacheOopDesc::decode_secondary_index(i); + return get_cpCacheOop()->entry_at(raw_index); + } + public: ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {} @@ -41,5 +53,7 @@ bool is_f1_null_at(int index); + int get_pool_index(int index); + void print(); };
--- a/hotspot/src/share/vm/ci/ciClassList.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciClassList.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -85,6 +85,7 @@ friend class ciConstantPoolCache; \ friend class ciField; \ friend class ciConstant; \ +friend class ciCPCache; \ friend class ciFlags; \ friend class ciExceptionHandler; \ friend class ciCallProfile; \
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -511,9 +511,22 @@ // // Implementation of get_constant_by_index(). ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool, - int index, + int pool_index, int cache_index, ciInstanceKlass* accessor) { + bool ignore_will_link; EXCEPTION_CONTEXT; + int index = pool_index; + if (cache_index >= 0) { + assert(index < 0, "only one kind of index at a time"); + ConstantPoolCacheEntry* cpc_entry = cpool->cache()->entry_at(cache_index); + index = cpc_entry->constant_pool_index(); + oop obj = cpc_entry->f1(); + if (obj != NULL) { + assert(obj->is_instance(), "must be an instance"); + ciObject* ciobj = get_object(obj); + return ciConstant(T_OBJECT, ciobj); + } + } constantTag tag = cpool->tag_at(index); if (tag.is_int()) { return ciConstant(T_INT, (jint)cpool->int_at(index)); @@ -540,8 +553,7 @@ return ciConstant(T_OBJECT, constant); } else if (tag.is_klass() || tag.is_unresolved_klass()) { // 4881222: allow ldc to take a class type - bool ignore; - ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor); + ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; record_out_of_memory_failure(); @@ -549,12 +561,26 @@ } assert (klass->is_instance_klass() || klass->is_array_klass(), "must be an instance or array klass "); - return ciConstant(T_OBJECT, klass); + return ciConstant(T_OBJECT, klass->java_mirror()); } else if (tag.is_object()) { oop obj = cpool->object_at(index); assert(obj->is_instance(), "must be an instance"); ciObject* ciobj = get_object(obj); return ciConstant(T_OBJECT, ciobj); + } else if (tag.is_method_type()) { + // must execute Java code to link this CP entry into cache[i].f1 + ciSymbol* signature = get_object(cpool->method_type_signature_at(index))->as_symbol(); + ciObject* ciobj = get_unloaded_method_type_constant(signature); + return ciConstant(T_OBJECT, ciobj); + } else if (tag.is_method_handle()) { + // must execute Java code to link this CP entry into cache[i].f1 + int ref_kind = cpool->method_handle_ref_kind_at(index); + int callee_index = cpool->method_handle_klass_index_at(index); + ciKlass* callee = get_klass_by_index_impl(cpool, callee_index, ignore_will_link, accessor); + ciSymbol* name = get_object(cpool->method_handle_name_ref_at(index))->as_symbol(); + ciSymbol* signature = get_object(cpool->method_handle_signature_ref_at(index))->as_symbol(); + ciObject* ciobj = get_unloaded_method_handle_constant(callee, name, signature, ref_kind); + return ciConstant(T_OBJECT, ciobj); } else { ShouldNotReachHere(); return ciConstant(); @@ -562,61 +588,15 @@ } // ------------------------------------------------------------------ -// ciEnv::is_unresolved_string_impl -// -// Implementation of is_unresolved_string(). -bool ciEnv::is_unresolved_string_impl(instanceKlass* accessor, int index) const { - EXCEPTION_CONTEXT; - assert(accessor->is_linked(), "must be linked before accessing constant pool"); - constantPoolOop cpool = accessor->constants(); - constantTag tag = cpool->tag_at(index); - return tag.is_unresolved_string(); -} - -// ------------------------------------------------------------------ -// ciEnv::is_unresolved_klass_impl -// -// Implementation of is_unresolved_klass(). -bool ciEnv::is_unresolved_klass_impl(instanceKlass* accessor, int index) const { - EXCEPTION_CONTEXT; - assert(accessor->is_linked(), "must be linked before accessing constant pool"); - constantPoolOop cpool = accessor->constants(); - constantTag tag = cpool->tag_at(index); - return tag.is_unresolved_klass(); -} - -// ------------------------------------------------------------------ // ciEnv::get_constant_by_index // // 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, - int index, + int pool_index, int cache_index, ciInstanceKlass* accessor) { - GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, index, accessor);) -} - -// ------------------------------------------------------------------ -// ciEnv::is_unresolved_string -// -// Check constant pool -// -// Implementation note: this query is currently in no way cached. -bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor, - int index) const { - GUARDED_VM_ENTRY(return is_unresolved_string_impl(accessor->get_instanceKlass(), index); ) -} - -// ------------------------------------------------------------------ -// ciEnv::is_unresolved_klass -// -// Check constant pool -// -// Implementation note: this query is currently in no way cached. -bool ciEnv::is_unresolved_klass(ciInstanceKlass* accessor, - int index) const { - GUARDED_VM_ENTRY(return is_unresolved_klass_impl(accessor->get_instanceKlass(), index); ) + GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, pool_index, cache_index, accessor);) } // ------------------------------------------------------------------ @@ -748,8 +728,8 @@ } // Get the invoker methodOop from the constant pool. - intptr_t f2_value = cpool->cache()->main_entry_at(index)->f2(); - methodOop signature_invoker = methodOop(f2_value); + oop f1_value = cpool->cache()->main_entry_at(index)->f1(); + methodOop signature_invoker = methodOop(f1_value); assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(), "correct result from LinkResolver::resolve_invokedynamic");
--- a/hotspot/src/share/vm/ci/ciEnv.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciEnv.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -116,12 +116,8 @@ bool& is_accessible, ciInstanceKlass* loading_klass); ciConstant get_constant_by_index(constantPoolHandle cpool, - int constant_index, + int pool_index, int cache_index, ciInstanceKlass* accessor); - bool is_unresolved_string(ciInstanceKlass* loading_klass, - int constant_index) const; - bool is_unresolved_klass(ciInstanceKlass* loading_klass, - int constant_index) const; ciField* get_field_by_index(ciInstanceKlass* loading_klass, int field_index); ciMethod* get_method_by_index(constantPoolHandle cpool, @@ -137,12 +133,8 @@ bool& is_accessible, ciInstanceKlass* loading_klass); ciConstant get_constant_by_index_impl(constantPoolHandle cpool, - int constant_index, + int pool_index, int cache_index, ciInstanceKlass* loading_klass); - bool is_unresolved_string_impl (instanceKlass* loading_klass, - int constant_index) const; - bool is_unresolved_klass_impl (instanceKlass* loading_klass, - int constant_index) const; ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass, int field_index); ciMethod* get_method_by_index_impl(constantPoolHandle cpool, @@ -190,6 +182,25 @@ return _factory->get_unloaded_klass(accessing_klass, name, true); } + // Get a ciKlass representing an unloaded klass mirror. + // Result is not necessarily unique, but will be unloaded. + ciInstance* get_unloaded_klass_mirror(ciKlass* type) { + return _factory->get_unloaded_klass_mirror(type); + } + + // Get a ciInstance representing an unresolved method handle constant. + ciInstance* get_unloaded_method_handle_constant(ciKlass* holder, + ciSymbol* name, + ciSymbol* signature, + int ref_kind) { + return _factory->get_unloaded_method_handle_constant(holder, name, signature, ref_kind); + } + + // Get a ciInstance representing an unresolved method type constant. + ciInstance* get_unloaded_method_type_constant(ciSymbol* signature) { + return _factory->get_unloaded_method_type_constant(signature); + } + // See if we already have an unloaded klass for the given name // or return NULL if not. ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) {
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * 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,9 +44,7 @@ _flags = ciFlags(access_flags); _has_finalizer = access_flags.has_finalizer(); _has_subklass = ik->subklass() != NULL; - _is_initialized = ik->is_initialized(); - // Next line must follow and use the result of the previous line: - _is_linked = _is_initialized || ik->is_linked(); + _init_state = (instanceKlass::ClassState)ik->get_init_state(); _nonstatic_field_size = ik->nonstatic_field_size(); _has_nonstatic_fields = ik->has_nonstatic_fields(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: @@ -91,8 +89,7 @@ : ciKlass(name, ciInstanceKlassKlass::make()) { assert(name->byte_at(0) != '[', "not an instance klass"); - _is_initialized = false; - _is_linked = false; + _init_state = (instanceKlass::ClassState)0; _nonstatic_field_size = -1; _has_nonstatic_fields = false; _nonstatic_fields = NULL; @@ -109,21 +106,10 @@ // ------------------------------------------------------------------ // ciInstanceKlass::compute_shared_is_initialized -bool ciInstanceKlass::compute_shared_is_initialized() { +void ciInstanceKlass::compute_shared_init_state() { GUARDED_VM_ENTRY( instanceKlass* ik = get_instanceKlass(); - _is_initialized = ik->is_initialized(); - return _is_initialized; - ) -} - -// ------------------------------------------------------------------ -// ciInstanceKlass::compute_shared_is_linked -bool ciInstanceKlass::compute_shared_is_linked() { - GUARDED_VM_ENTRY( - instanceKlass* ik = get_instanceKlass(); - _is_linked = ik->is_linked(); - return _is_linked; + _init_state = (instanceKlass::ClassState)ik->get_init_state(); ) } @@ -323,8 +309,8 @@ // ciInstanceKlass::java_mirror // // Get the instance of java.lang.Class corresponding to this klass. +// Cache it on this->_java_mirror. ciInstance* ciInstanceKlass::java_mirror() { - assert(is_loaded(), "must be loaded"); if (_java_mirror == NULL) { _java_mirror = ciKlass::java_mirror(); }
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * 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,9 +39,8 @@ jobject _loader; jobject _protection_domain; + instanceKlass::ClassState _init_state; // state of class bool _is_shared; - bool _is_initialized; - bool _is_linked; bool _has_finalizer; bool _has_subklass; bool _has_nonstatic_fields; @@ -87,27 +86,34 @@ bool is_shared() { return _is_shared; } - bool compute_shared_is_initialized(); - bool compute_shared_is_linked(); + void compute_shared_init_state(); bool compute_shared_has_subklass(); int compute_shared_nof_implementors(); int compute_nonstatic_fields(); GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields); + // Update the init_state for shared klasses + void update_if_shared(instanceKlass::ClassState expected) { + if (_is_shared && _init_state != expected) { + if (is_loaded()) compute_shared_init_state(); + } + } + public: // Has this klass been initialized? bool is_initialized() { - if (_is_shared && !_is_initialized) { - return is_loaded() && compute_shared_is_initialized(); - } - return _is_initialized; + update_if_shared(instanceKlass::fully_initialized); + return _init_state == instanceKlass::fully_initialized; + } + // Is this klass being initialized? + bool is_being_initialized() { + update_if_shared(instanceKlass::being_initialized); + return _init_state == instanceKlass::being_initialized; } // Has this klass been linked? bool is_linked() { - if (_is_shared && !_is_linked) { - return is_loaded() && compute_shared_is_linked(); - } - return _is_linked; + update_if_shared(instanceKlass::linked); + return _init_state >= instanceKlass::linked; } // General klass information.
--- a/hotspot/src/share/vm/ci/ciKlass.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciKlass.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -192,8 +192,14 @@ // ------------------------------------------------------------------ // ciKlass::java_mirror +// +// Get the instance of java.lang.Class corresponding to this klass. +// If it is an unloaded instance or array klass, return an unloaded +// mirror object of type Class. ciInstance* ciKlass::java_mirror() { GUARDED_VM_ENTRY( + if (!is_loaded()) + return ciEnv::current()->get_unloaded_klass_mirror(this); oop java_mirror = get_Klass()->java_mirror(); return CURRENT_ENV->get_object(java_mirror)->as_instance(); )
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciMethod.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -54,10 +54,10 @@ _code = NULL; _exception_handlers = NULL; _liveness = NULL; - _bcea = NULL; _method_blocks = NULL; #ifdef COMPILER2 _flow = NULL; + _bcea = NULL; #endif // COMPILER2 ciEnv *env = CURRENT_ENV; @@ -121,11 +121,11 @@ _intrinsic_id = vmIntrinsics::_none; _liveness = NULL; _can_be_statically_bound = false; - _bcea = NULL; _method_blocks = NULL; _method_data = NULL; #ifdef COMPILER2 _flow = NULL; + _bcea = NULL; #endif // COMPILER2 } @@ -694,30 +694,21 @@ // ------------------------------------------------------------------ // ciMethod::is_method_handle_invoke // -// Return true if the method is a MethodHandle target. +// Return true if the method is an instance of one of the two +// signature-polymorphic MethodHandle methods, invokeExact or invokeGeneric. bool ciMethod::is_method_handle_invoke() const { - bool flag = (holder()->name() == ciSymbol::java_dyn_MethodHandle() && - methodOopDesc::is_method_handle_invoke_name(name()->sid())); -#ifdef ASSERT - if (is_loaded()) { - bool flag2 = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS); - { - VM_ENTRY_MARK; - bool flag3 = get_methodOop()->is_method_handle_invoke(); - assert(flag2 == flag3, "consistent"); - assert(flag == flag3, "consistent"); - } - } -#endif //ASSERT - return flag; + if (!is_loaded()) return false; + VM_ENTRY_MARK; + return get_methodOop()->is_method_handle_invoke(); } // ------------------------------------------------------------------ // ciMethod::is_method_handle_adapter // // Return true if the method is a generated MethodHandle adapter. +// These are built by MethodHandleCompiler. bool ciMethod::is_method_handle_adapter() const { - check_is_loaded(); + if (!is_loaded()) return false; VM_ENTRY_MARK; return get_methodOop()->is_method_handle_adapter(); } @@ -1033,10 +1024,15 @@ bool ciMethod::is_initializer () const { FETCH_FLAG_FROM_VM(is_initializer); } BCEscapeAnalyzer *ciMethod::get_bcea() { +#ifdef COMPILER2 if (_bcea == NULL) { _bcea = new (CURRENT_ENV->arena()) BCEscapeAnalyzer(this, NULL); } return _bcea; +#else // COMPILER2 + ShouldNotReachHere(); + return NULL; +#endif // COMPILER2 } ciMethodBlocks *ciMethod::get_method_blocks() {
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciMethod.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -48,7 +48,6 @@ ciInstanceKlass* _holder; ciSignature* _signature; ciMethodData* _method_data; - BCEscapeAnalyzer* _bcea; ciMethodBlocks* _method_blocks; // Code attributes. @@ -72,7 +71,8 @@ // Optional liveness analyzer. MethodLiveness* _liveness; #ifdef COMPILER2 - ciTypeFlow* _flow; + ciTypeFlow* _flow; + BCEscapeAnalyzer* _bcea; #endif ciMethod(methodHandle h_m);
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -70,6 +70,7 @@ _unloaded_methods = new (arena) GrowableArray<ciMethod*>(arena, 4, 0, NULL); _unloaded_klasses = new (arena) GrowableArray<ciKlass*>(arena, 8, 0, NULL); + _unloaded_instances = new (arena) GrowableArray<ciInstance*>(arena, 4, 0, NULL); _return_addresses = new (arena) GrowableArray<ciReturnAddress*>(arena, 8, 0, NULL); } @@ -443,6 +444,74 @@ return new_klass; } + +//------------------------------------------------------------------ +// ciObjectFactory::get_unloaded_instance +// +// Get a ciInstance representing an as-yet undetermined instance of a given class. +// +ciInstance* ciObjectFactory::get_unloaded_instance(ciInstanceKlass* instance_klass) { + for (int i=0; i<_unloaded_instances->length(); i++) { + ciInstance* entry = _unloaded_instances->at(i); + if (entry->klass()->equals(instance_klass)) { + // We've found a match. + return entry; + } + } + + // This is a new unloaded instance. Create it and stick it in + // the cache. + ciInstance* new_instance = new (arena()) ciInstance(instance_klass); + + init_ident_of(new_instance); + _unloaded_instances->append(new_instance); + + // make sure it looks the way we want: + assert(!new_instance->is_loaded(), ""); + assert(new_instance->klass() == instance_klass, ""); + + return new_instance; +} + + +//------------------------------------------------------------------ +// ciObjectFactory::get_unloaded_klass_mirror +// +// Get a ciInstance representing an unresolved klass mirror. +// +// Currently, this ignores the parameters and returns a unique unloaded instance. +ciInstance* ciObjectFactory::get_unloaded_klass_mirror(ciKlass* type) { + assert(ciEnv::_Class_klass != NULL, ""); + return get_unloaded_instance(ciEnv::_Class_klass->as_instance_klass()); +} + +//------------------------------------------------------------------ +// ciObjectFactory::get_unloaded_method_handle_constant +// +// Get a ciInstance representing an unresolved method handle constant. +// +// Currently, this ignores the parameters and returns a unique unloaded instance. +ciInstance* ciObjectFactory::get_unloaded_method_handle_constant(ciKlass* holder, + ciSymbol* name, + ciSymbol* signature, + int ref_kind) { + if (ciEnv::_MethodHandle_klass == NULL) return NULL; + return get_unloaded_instance(ciEnv::_MethodHandle_klass->as_instance_klass()); +} + +//------------------------------------------------------------------ +// ciObjectFactory::get_unloaded_method_type_constant +// +// Get a ciInstance representing an unresolved method type constant. +// +// Currently, this ignores the parameters and returns a unique unloaded instance. +ciInstance* ciObjectFactory::get_unloaded_method_type_constant(ciSymbol* signature) { + if (ciEnv::_MethodType_klass == NULL) return NULL; + return get_unloaded_instance(ciEnv::_MethodType_klass->as_instance_klass()); +} + + + //------------------------------------------------------------------ // ciObjectFactory::get_empty_methodData // @@ -637,7 +706,8 @@ // // Print debugging information about the object factory void ciObjectFactory::print() { - tty->print("<ciObjectFactory oops=%d unloaded_methods=%d unloaded_klasses=%d>", + tty->print("<ciObjectFactory oops=%d unloaded_methods=%d unloaded_instances=%d unloaded_klasses=%d>", _ci_objects->length(), _unloaded_methods->length(), + _unloaded_instances->length(), _unloaded_klasses->length()); }
--- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -39,6 +39,7 @@ GrowableArray<ciObject*>* _ci_objects; GrowableArray<ciMethod*>* _unloaded_methods; GrowableArray<ciKlass*>* _unloaded_klasses; + GrowableArray<ciInstance*>* _unloaded_instances; GrowableArray<ciReturnAddress*>* _return_addresses; int _next_ident; @@ -73,6 +74,8 @@ void print_contents_impl(); + ciInstance* get_unloaded_instance(ciInstanceKlass* klass); + public: static bool is_initialized() { return _initialized; } @@ -98,6 +101,18 @@ ciSymbol* name, bool create_if_not_found); + // Get a ciInstance representing an unresolved klass mirror. + ciInstance* get_unloaded_klass_mirror(ciKlass* type); + + // Get a ciInstance representing an unresolved method handle constant. + ciInstance* get_unloaded_method_handle_constant(ciKlass* holder, + ciSymbol* name, + ciSymbol* signature, + int ref_kind); + + // Get a ciInstance representing an unresolved method type constant. + ciInstance* get_unloaded_method_type_constant(ciSymbol* signature); + // Get the ciMethodData representing the methodData for a method // with none.
--- a/hotspot/src/share/vm/ci/ciStreams.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciStreams.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -186,12 +186,13 @@ } // ------------------------------------------------------------------ -// ciBytecodeStream::get_constant_index +// ciBytecodeStream::get_constant_raw_index // // If this bytecode is one of the ldc variants, get the index of the // referenced constant. -int ciBytecodeStream::get_constant_index() const { - switch(cur_bc()) { +int ciBytecodeStream::get_constant_raw_index() const { + // work-alike for Bytecode_loadconstant::raw_index() + switch (cur_bc()) { case Bytecodes::_ldc: return get_index_u1(); case Bytecodes::_ldc_w: @@ -202,25 +203,52 @@ return 0; } } + +// ------------------------------------------------------------------ +// ciBytecodeStream::get_constant_pool_index +// Decode any CP cache index into a regular pool index. +int ciBytecodeStream::get_constant_pool_index() const { + // work-alike for Bytecode_loadconstant::pool_index() + int index = get_constant_raw_index(); + if (has_cache_index()) { + return get_cpcache()->get_pool_index(index); + } + return index; +} + +// ------------------------------------------------------------------ +// ciBytecodeStream::get_constant_cache_index +// Return the CP cache index, or -1 if there isn't any. +int ciBytecodeStream::get_constant_cache_index() const { + // work-alike for Bytecode_loadconstant::cache_index() + return has_cache_index() ? get_constant_raw_index() : -1; +} + // ------------------------------------------------------------------ // ciBytecodeStream::get_constant // // If this bytecode is one of the ldc variants, get the referenced // constant. ciConstant ciBytecodeStream::get_constant() { + int pool_index = get_constant_raw_index(); + int cache_index = -1; + if (has_cache_index()) { + cache_index = pool_index; + pool_index = -1; + } VM_ENTRY_MARK; constantPoolHandle cpool(_method->get_methodOop()->constants()); - return CURRENT_ENV->get_constant_by_index(cpool, get_constant_index(), _holder); + return CURRENT_ENV->get_constant_by_index(cpool, pool_index, cache_index, _holder); } // ------------------------------------------------------------------ -bool ciBytecodeStream::is_unresolved_string() const { - return CURRENT_ENV->is_unresolved_string(_holder, get_constant_index()); -} - -// ------------------------------------------------------------------ -bool ciBytecodeStream::is_unresolved_klass() const { - return CURRENT_ENV->is_unresolved_klass(_holder, get_klass_index()); +// ciBytecodeStream::get_constant_pool_tag +// +// If this bytecode is one of the ldc variants, get the referenced +// constant. +constantTag ciBytecodeStream::get_constant_pool_tag(int index) const { + VM_ENTRY_MARK; + return _method->get_methodOop()->constants()->tag_at(index); } // ------------------------------------------------------------------ @@ -378,13 +406,16 @@ // ------------------------------------------------------------------ // ciBytecodeStream::get_cpcache -ciCPCache* ciBytecodeStream::get_cpcache() { - VM_ENTRY_MARK; - // Get the constant pool. - constantPoolOop cpool = _holder->get_instanceKlass()->constants(); - constantPoolCacheOop cpcache = cpool->cache(); +ciCPCache* ciBytecodeStream::get_cpcache() const { + if (_cpcache == NULL) { + VM_ENTRY_MARK; + // Get the constant pool. + constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + constantPoolCacheOop cpcache = cpool->cache(); - return CURRENT_ENV->get_object(cpcache)->as_cpcache(); + *(ciCPCache**)&_cpcache = CURRENT_ENV->get_object(cpcache)->as_cpcache(); + } + return _cpcache; } // ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciStreams.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciStreams.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -46,6 +46,7 @@ ciMethod* _method; // the method ciInstanceKlass* _holder; + ciCPCache* _cpcache; address _bc_start; // Start of current bytecode for table address _was_wide; // Address past last wide bytecode jint* _table_base; // Aligned start of last table or switch @@ -58,7 +59,9 @@ void reset( address base, unsigned int size ) { _bc_start =_was_wide = 0; - _start = _pc = base; _end = base + size; } + _start = _pc = base; _end = base + size; + _cpcache = NULL; + } void assert_wide(bool require_wide) const { if (require_wide) @@ -136,15 +139,20 @@ bool is_wide() const { return ( _pc == _was_wide ); } // Does this instruction contain an index which refes into the CP cache? - bool uses_cp_cache() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); } + bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); } int get_index_u1() const { return bytecode()->get_index_u1(cur_bc_raw()); } + int get_index_u1_cpcache() const { + return bytecode()->get_index_u1_cpcache(cur_bc_raw()); + } + // Get a byte index following this bytecode. // If prefixed with a wide bytecode, get a wide index. int get_index() const { + assert(!has_cache_index(), "else use cpcache variant"); return (_pc == _was_wide) // was widened? ? get_index_u2(true) // yes, return wide index : get_index_u1(); // no, return narrow index @@ -207,7 +215,9 @@ return cur_bci() + get_int_table(index); } // --- Constant pool access --- - int get_constant_index() const; + int get_constant_raw_index() const; + int get_constant_pool_index() const; + int get_constant_cache_index() const; int get_field_index(); int get_method_index(); @@ -217,12 +227,17 @@ int get_klass_index() const; // If this bytecode is one of the ldc variants, get the referenced - // constant + // constant. Do not attempt to resolve it, since that would require + // execution of Java code. If it is not resolved, return an unloaded + // object (ciConstant.as_object()->is_loaded() == false). ciConstant get_constant(); - // True if the ldc variant points to an unresolved string - bool is_unresolved_string() const; - // True if the ldc variant points to an unresolved klass - bool is_unresolved_klass() const; + constantTag get_constant_pool_tag(int index) const; + + // True if the klass-using bytecode points to an unresolved klass + bool is_unresolved_klass() const { + constantTag tag = get_constant_pool_tag(get_klass_index()); + return tag.is_unresolved_klass(); + } // If this bytecode is one of get_field, get_static, put_field, // or put_static, get the referenced field. @@ -238,7 +253,7 @@ int get_method_holder_index(); int get_method_signature_index(); - ciCPCache* get_cpcache(); + ciCPCache* get_cpcache() const; ciCallSite* get_call_site(); };
--- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -712,10 +712,8 @@ ciObject* obj = con.as_object(); if (obj->is_null_object()) { push_null(); - } else if (obj->is_klass()) { - // The type of ldc <class> is java.lang.Class - push_object(outer()->env()->Class_klass()); } else { + assert(!obj->is_klass(), "must be java_mirror of klass"); push_object(obj->klass()); } } else {
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -117,6 +117,45 @@ cp->string_index_at_put(index, string_index); } break; + case JVM_CONSTANT_MethodHandle : + case JVM_CONSTANT_MethodType : + if (!EnableMethodHandles || + _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { + classfile_parse_error( + (!EnableMethodHandles ? + "This JVM does not support constant tag %u in class file %s" : + "Class file version does not support constant tag %u in class file %s"), + tag, CHECK); + } + if (tag == JVM_CONSTANT_MethodHandle) { + cfs->guarantee_more(4, CHECK); // ref_kind, method_index, tag/access_flags + u1 ref_kind = cfs->get_u1_fast(); + u2 method_index = cfs->get_u2_fast(); + cp->method_handle_index_at_put(index, ref_kind, method_index); + } else if (tag == JVM_CONSTANT_MethodType) { + cfs->guarantee_more(3, CHECK); // signature_index, tag/access_flags + u2 signature_index = cfs->get_u2_fast(); + cp->method_type_index_at_put(index, signature_index); + } else { + ShouldNotReachHere(); + } + break; + case JVM_CONSTANT_InvokeDynamic : + { + if (!EnableInvokeDynamic || + _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { + classfile_parse_error( + (!EnableInvokeDynamic ? + "This JVM does not support constant tag %u in class file %s" : + "Class file version does not support constant tag %u in class file %s"), + tag, CHECK); + } + cfs->guarantee_more(5, CHECK); // bsm_index, name_and_type_index, tag/access_flags + u2 bootstrap_method_index = cfs->get_u2_fast(); + u2 name_and_type_index = cfs->get_u2_fast(); + cp->invoke_dynamic_at_put(index, bootstrap_method_index, name_and_type_index); + } + break; case JVM_CONSTANT_Integer : { cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags @@ -337,6 +376,78 @@ cp->unresolved_string_at_put(index, sym); } break; + case JVM_CONSTANT_MethodHandle : + { + int ref_index = cp->method_handle_index_at(index); + check_property( + valid_cp_range(ref_index, length) && + EnableMethodHandles, + "Invalid constant pool index %u in class file %s", + ref_index, CHECK_(nullHandle)); + constantTag tag = cp->tag_at(ref_index); + int ref_kind = cp->method_handle_ref_kind_at(index); + switch (ref_kind) { + case JVM_REF_getField: + case JVM_REF_getStatic: + case JVM_REF_putField: + case JVM_REF_putStatic: + check_property( + tag.is_field(), + "Invalid constant pool index %u in class file %s (not a field)", + ref_index, CHECK_(nullHandle)); + break; + case JVM_REF_invokeVirtual: + case JVM_REF_invokeStatic: + case JVM_REF_invokeSpecial: + case JVM_REF_newInvokeSpecial: + check_property( + tag.is_method(), + "Invalid constant pool index %u in class file %s (not a method)", + ref_index, CHECK_(nullHandle)); + break; + case JVM_REF_invokeInterface: + check_property( + tag.is_interface_method(), + "Invalid constant pool index %u in class file %s (not an interface method)", + ref_index, CHECK_(nullHandle)); + break; + default: + classfile_parse_error( + "Bad method handle kind at constant pool index %u in class file %s", + index, CHECK_(nullHandle)); + } + // Keep the ref_index unchanged. It will be indirected at link-time. + } + break; + case JVM_CONSTANT_MethodType : + { + int ref_index = cp->method_type_index_at(index); + check_property( + valid_cp_range(ref_index, length) && + cp->tag_at(ref_index).is_utf8() && + EnableMethodHandles, + "Invalid constant pool index %u in class file %s", + ref_index, CHECK_(nullHandle)); + } + break; + case JVM_CONSTANT_InvokeDynamic : + { + int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); + int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index); + check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) + || + (valid_cp_range(bootstrap_method_ref_index, length) && + cp->tag_at(bootstrap_method_ref_index).is_method_handle()), + "Invalid constant pool index %u in class file %s", + bootstrap_method_ref_index, + CHECK_(nullHandle)); + check_property(valid_cp_range(name_and_type_ref_index, length) && + cp->tag_at(name_and_type_ref_index).is_name_and_type(), + "Invalid constant pool index %u in class file %s", + name_and_type_ref_index, + CHECK_(nullHandle)); + break; + } default: fatal(err_msg("bad constant pool tag value %u", cp->tag_at(index).value())); @@ -452,6 +563,43 @@ } break; } + case JVM_CONSTANT_MethodHandle: { + int ref_index = cp->method_handle_index_at(index); + int ref_kind = cp->method_handle_ref_kind_at(index); + switch (ref_kind) { + case JVM_REF_invokeVirtual: + case JVM_REF_invokeStatic: + case JVM_REF_invokeSpecial: + case JVM_REF_newInvokeSpecial: + { + int name_and_type_ref_index = cp->name_and_type_ref_index_at(ref_index); + int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index); + symbolHandle name(THREAD, cp->symbol_at(name_ref_index)); + if (ref_kind == JVM_REF_newInvokeSpecial) { + if (name() != vmSymbols::object_initializer_name()) { + classfile_parse_error( + "Bad constructor name at constant pool index %u in class file %s", + name_ref_index, CHECK_(nullHandle)); + } + } else { + if (name() == vmSymbols::object_initializer_name()) { + classfile_parse_error( + "Bad method name at constant pool index %u in class file %s", + name_ref_index, CHECK_(nullHandle)); + } + } + } + break; + // Other ref_kinds are already fully checked in previous pass. + } + break; + } + case JVM_CONSTANT_MethodType: { + symbolHandle no_name = vmSymbolHandles::type_name(); // place holder + symbolHandle signature(THREAD, cp->method_type_signature_at(index)); + verify_legal_method_signature(no_name, signature, CHECK_(nullHandle)); + break; + } } // end of switch } // end of for @@ -467,7 +615,7 @@ case JVM_CONSTANT_UnresolvedClass : // Patching a class means pre-resolving it. // The name in the constant pool is ignored. - if (patch->klass() == SystemDictionary::Class_klass()) { // %%% java_lang_Class::is_instance + if (java_lang_Class::is_instance(patch())) { guarantee_property(!java_lang_Class::is_primitive(patch()), "Illegal class patch at %d in class file %s", index, CHECK);
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/classfile/classLoader.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -832,7 +832,6 @@ instanceKlassHandle ClassLoader::load_classfile(symbolHandle h_name, TRAPS) { - VTuneClassLoadMarker clm; ResourceMark rm(THREAD); EventMark m("loading class " INTPTR_FORMAT, (address)h_name()); ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -2454,6 +2454,48 @@ return Handle(THREAD, (oop) result.get_jobject()); } +// Ask Java code to find or construct a method handle constant. +Handle SystemDictionary::link_method_handle_constant(KlassHandle caller, + int ref_kind, //e.g., JVM_REF_invokeVirtual + KlassHandle callee, + symbolHandle name_sym, + symbolHandle signature, + TRAPS) { + Handle empty; + Handle name = java_lang_String::create_from_symbol(name_sym(), CHECK_(empty)); + Handle type; + if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') { + bool ignore_is_on_bcp = false; + type = find_method_handle_type(signature, caller, ignore_is_on_bcp, CHECK_(empty)); + } else { + SignatureStream ss(signature(), false); + if (!ss.is_done()) { + oop mirror = ss.as_java_mirror(caller->class_loader(), caller->protection_domain(), + SignatureStream::NCDFError, CHECK_(empty)); + type = Handle(THREAD, mirror); + ss.next(); + if (!ss.is_done()) type = Handle(); // error! + } + } + if (type.is_null()) { + THROW_MSG_(vmSymbols::java_lang_LinkageError(), "bad signature", empty); + } + + // call sun.dyn.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle + JavaCallArguments args; + args.push_oop(caller->java_mirror()); // the referring class + args.push_int(ref_kind); + args.push_oop(callee->java_mirror()); // the target class + args.push_oop(name()); + args.push_oop(type()); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, + SystemDictionary::MethodHandleNatives_klass(), + vmSymbols::linkMethodHandleConstant_name(), + vmSymbols::linkMethodHandleConstant_signature(), + &args, CHECK_(empty)); + return Handle(THREAD, (oop) result.get_jobject()); +} // Ask Java code to find or construct a java.dyn.CallSite for the given // name and signature, as interpreted relative to the given class loader. @@ -2465,6 +2507,10 @@ int caller_bci, TRAPS) { Handle empty; + guarantee(bootstrap_method.not_null() && + java_dyn_MethodHandle::is_instance(bootstrap_method()), + "caller must supply a valid BSM"); + Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty)); MethodHandles::init_MemberName(caller_mname(), caller_method()); @@ -2495,20 +2541,61 @@ return call_site_oop; } -Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, TRAPS) { +Handle SystemDictionary::find_bootstrap_method(methodHandle caller_method, int caller_bci, + int cache_index, TRAPS) { Handle empty; - if (!caller->oop_is_instance()) return empty; - - instanceKlassHandle ik(THREAD, caller()); - - oop boot_method_oop = ik->bootstrap_method(); - if (boot_method_oop != NULL) { + + constantPoolHandle pool; + { + klassOop caller = caller_method->method_holder(); + if (!Klass::cast(caller)->oop_is_instance()) return empty; + pool = constantPoolHandle(THREAD, instanceKlass::cast(caller)->constants()); + } + + int constant_pool_index = pool->cache()->entry_at(cache_index)->constant_pool_index(); + constantTag tag = pool->tag_at(constant_pool_index); + + if (tag.is_invoke_dynamic()) { + // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&type] + // The bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry. + int bsm_index = pool->invoke_dynamic_bootstrap_method_ref_index_at(constant_pool_index); + if (bsm_index != 0) { + int bsm_index_in_cache = pool->cache()->entry_at(cache_index)->bootstrap_method_index_in_cache(); + DEBUG_ONLY(int bsm_index_2 = pool->cache()->entry_at(bsm_index_in_cache)->constant_pool_index()); + assert(bsm_index == bsm_index_2, "BSM constant lifted to cache"); + if (TraceMethodHandles) { + tty->print_cr("resolving bootstrap method for "PTR_FORMAT" at %d at cache[%d]CP[%d]...", + (intptr_t) caller_method(), caller_bci, cache_index, constant_pool_index); + } + oop bsm_oop = pool->resolve_cached_constant_at(bsm_index_in_cache, CHECK_(empty)); + if (TraceMethodHandles) { + tty->print_cr("bootstrap method for "PTR_FORMAT" at %d retrieved as "PTR_FORMAT":", + (intptr_t) caller_method(), caller_bci, (intptr_t) bsm_oop); + } + assert(bsm_oop->is_oop() + && java_dyn_MethodHandle::is_instance(bsm_oop), "must be sane"); + return Handle(THREAD, bsm_oop); + } + // else null BSM; fall through + } else if (tag.is_name_and_type()) { + // JSR 292 EDR does not have JVM_CONSTANT_InvokeDynamic + // a bare name&type defaults its BSM to null, so fall through... + } else { + ShouldNotReachHere(); // verifier does not allow this + } + + // Fall through to pick up the per-class bootstrap method. + // This mechanism may go away in the PFD. + assert(AllowTransitionalJSR292, "else the verifier should have stopped us already"); + oop bsm_oop = instanceKlass::cast(caller_method->method_holder())->bootstrap_method(); + if (bsm_oop != NULL) { if (TraceMethodHandles) { - tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop); + tty->print_cr("bootstrap method for "PTR_FORMAT" registered as "PTR_FORMAT":", + (intptr_t) caller_method(), (intptr_t) bsm_oop); } - assert(boot_method_oop->is_oop() - && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); - return Handle(THREAD, boot_method_oop); + assert(bsm_oop->is_oop() + && java_dyn_MethodHandle::is_instance(bsm_oop), "must be sane"); + return Handle(THREAD, bsm_oop); } return empty;
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -473,6 +473,13 @@ KlassHandle accessing_klass, bool& return_bcp_flag, TRAPS); + // ask Java to compute a java.dyn.MethodHandle object for a given CP entry + static Handle link_method_handle_constant(KlassHandle caller, + int ref_kind, //e.g., JVM_REF_invokeVirtual + KlassHandle callee, + symbolHandle name, + symbolHandle signature, + TRAPS); // ask Java to create a dynamic call site, while linking an invokedynamic op static Handle make_dynamic_call_site(Handle bootstrap_method, // Callee information: @@ -485,7 +492,10 @@ TRAPS); // coordinate with Java about bootstrap methods - static Handle find_bootstrap_method(KlassHandle caller, TRAPS); + static Handle find_bootstrap_method(methodHandle caller_method, + int caller_bci, // N.B. must be an invokedynamic + int cache_index, // must be corresponding main_entry + TRAPS); // Utility for printing loader "name" as part of tracing constraints static const char* loader_name(oop loader) {
--- a/hotspot/src/share/vm/classfile/verifier.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -1598,7 +1598,10 @@ if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) { if (!tag.is_unresolved_string() && !tag.is_unresolved_klass()) { types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float) - | (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class); + | (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class) + | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType); + // Note: The class file parser already verified the legality of + // MethodHandle and MethodType constants. verify_cp_type(index, cp, types, CHECK_VERIFY(this)); } } else { @@ -1632,6 +1635,14 @@ current_frame->push_stack_2( VerificationType::long_type(), VerificationType::long2_type(), CHECK_VERIFY(this)); + } else if (tag.is_method_handle()) { + current_frame->push_stack( + VerificationType::reference_type( + vmSymbols::java_dyn_MethodHandle()), CHECK_VERIFY(this)); + } else if (tag.is_method_type()) { + current_frame->push_stack( + VerificationType::reference_type( + vmSymbols::java_dyn_MethodType()), CHECK_VERIFY(this)); } else { verify_error(bci, "Invalid index in ldc"); return; @@ -1902,7 +1913,8 @@ unsigned int types = (opcode == Bytecodes::_invokeinterface ? 1 << JVM_CONSTANT_InterfaceMethodref : opcode == Bytecodes::_invokedynamic - ? 1 << JVM_CONSTANT_NameAndType + ? (1 << JVM_CONSTANT_NameAndType + |1 << JVM_CONSTANT_InvokeDynamic) : 1 << JVM_CONSTANT_Methodref); verify_cp_type(index, cp, types, CHECK_VERIFY(this)); @@ -1920,9 +1932,12 @@ // Get referenced class type VerificationType ref_class_type; if (opcode == Bytecodes::_invokedynamic) { - if (!EnableInvokeDynamic) { + if (!EnableInvokeDynamic || + _klass->major_version() < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { class_format_error( - "invokedynamic instructions not enabled on this JVM", + (!EnableInvokeDynamic ? + "invokedynamic instructions not enabled in this JVM" : + "invokedynamic instructions not supported by this class file version"), _klass->external_name()); return; }
--- a/hotspot/src/share/vm/classfile/verifier.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/classfile/verifier.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -25,7 +25,10 @@ // The verifier class class Verifier : AllStatic { public: - enum { STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50 }; + enum { + STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50, + INVOKEDYNAMIC_MAJOR_VERSION = 51 + }; typedef enum { ThrowException, NoException } Mode; /**
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -246,6 +246,8 @@ /* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \ template(findMethodHandleType_name, "findMethodHandleType") \ template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \ + template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \ + template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") \ template(makeDynamicCallSite_name, "makeDynamicCallSite") \ template(makeDynamicCallSite_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") \ NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
--- a/hotspot/src/share/vm/code/codeBlob.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/code/codeBlob.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -202,6 +202,11 @@ //---------------------------------------------------------------------------------------------------- // Implementation of AdapterBlob +AdapterBlob::AdapterBlob(int size, CodeBuffer* cb) : + BufferBlob("I2C/C2I adapters", size, cb) { + CodeCache::commit(this); +} + AdapterBlob* AdapterBlob::create(CodeBuffer* cb) { ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock @@ -281,7 +286,6 @@ tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, stub); Disassembler::decode(stub->instructions_begin(), stub->instructions_end()); } - VTune::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end()); Forte::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end()); if (JvmtiExport::should_post_dynamic_code_generated()) { @@ -356,7 +360,6 @@ tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob); Disassembler::decode(blob->instructions_begin(), blob->instructions_end()); } - VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end()); Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end()); if (JvmtiExport::should_post_dynamic_code_generated()) { @@ -414,7 +417,6 @@ tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob); Disassembler::decode(blob->instructions_begin(), blob->instructions_end()); } - VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end()); Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end()); if (JvmtiExport::should_post_dynamic_code_generated()) { @@ -474,7 +476,6 @@ tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob); Disassembler::decode(blob->instructions_begin(), blob->instructions_end()); } - VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end()); Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end()); if (JvmtiExport::should_post_dynamic_code_generated()) { @@ -533,7 +534,6 @@ tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob); Disassembler::decode(blob->instructions_begin(), blob->instructions_end()); } - VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end()); Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end()); if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/code/codeBlob.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/code/codeBlob.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -219,8 +219,7 @@ class AdapterBlob: public BufferBlob { private: - AdapterBlob(int size) : BufferBlob("I2C/C2I adapters", size) {} - AdapterBlob(int size, CodeBuffer* cb) : BufferBlob("I2C/C2I adapters", size, cb) {} + AdapterBlob(int size, CodeBuffer* cb); public: // Creation
--- a/hotspot/src/share/vm/code/codeCache.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/code/codeCache.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -93,6 +93,8 @@ CodeHeap * CodeCache::_heap = new CodeHeap(); int CodeCache::_number_of_blobs = 0; +int CodeCache::_number_of_adapters = 0; +int CodeCache::_number_of_nmethods = 0; int CodeCache::_number_of_nmethods_with_dependencies = 0; bool CodeCache::_needs_cache_clean = false; nmethod* CodeCache::_scavenge_root_nmethods = NULL; @@ -176,8 +178,14 @@ verify_if_often(); print_trace("free", cb); - if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) { - _number_of_nmethods_with_dependencies--; + if (cb->is_nmethod()) { + _number_of_nmethods--; + if (((nmethod *)cb)->has_dependencies()) { + _number_of_nmethods_with_dependencies--; + } + } + if (cb->is_adapter_blob()) { + _number_of_adapters--; } _number_of_blobs--; @@ -191,9 +199,16 @@ void CodeCache::commit(CodeBlob* cb) { // this is called by nmethod::nmethod, which must already own CodeCache_lock assert_locked_or_safepoint(CodeCache_lock); - if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) { - _number_of_nmethods_with_dependencies++; + if (cb->is_nmethod()) { + _number_of_nmethods++; + if (((nmethod *)cb)->has_dependencies()) { + _number_of_nmethods_with_dependencies++; + } } + if (cb->is_adapter_blob()) { + _number_of_adapters++; + } + // flush the hardware I-cache ICache::invalidate_range(cb->instructions_begin(), cb->instructions_size()); }
--- a/hotspot/src/share/vm/code/codeCache.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/code/codeCache.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * 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,6 +43,8 @@ // 4422213 or 4436291 for details. static CodeHeap * _heap; static int _number_of_blobs; + static int _number_of_adapters; + static int _number_of_nmethods; static int _number_of_nmethods_with_dependencies; static bool _needs_cache_clean; static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link() @@ -105,6 +107,8 @@ static nmethod* first_nmethod(); static nmethod* next_nmethod (CodeBlob* cb); static int nof_blobs() { return _number_of_blobs; } + static int nof_adapters() { return _number_of_adapters; } + static int nof_nmethods() { return _number_of_nmethods; } // GC support static void gc_epilogue();
--- a/hotspot/src/share/vm/code/nmethod.cpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/code/nmethod.cpp Sat Jul 31 15:10:59 2010 +0100 @@ -397,11 +397,6 @@ //-------------end of code for ExceptionCache-------------- -void nmFlags::clear() { - assert(sizeof(nmFlags) == sizeof(int), "using more than one word for nmFlags"); - *(jint*)this = 0; -} - int nmethod::total_size() const { return code_size() + @@ -419,8 +414,32 @@ return NULL; } -// %%% This variable is no longer used? -int nmethod::_zombie_instruction_size = NativeJump::instruction_size; +// Fill in default values for various flag fields +void nmethod::init_defaults() { + _state = alive; + _marked_for_reclamation = 0; + _has_flushed_dependencies = 0; + _speculatively_disconnected = 0; + _has_unsafe_access = 0; + _has_method_handle_invokes = 0; + _marked_for_deoptimization = 0; + _lock_count = 0; + _stack_traversal_mark = 0; + _unload_reported = false; // jvmti state + + NOT_PRODUCT(_has_debug_info = false); + _oops_do_mark_link = NULL; + _jmethod_id = NULL; + _osr_link = NULL; + _scavenge_root_link = NULL; + _scavenge_root_state = 0; + _saved_nmethod_link = NULL; + _compiler = NULL; + +#ifdef HAVE_DTRACE_H + _trap_offset = 0; +#endif // def HAVE_DTRACE_H +} nmethod* nmethod::new_native_nmethod(methodHandle method, @@ -580,24 +599,16 @@ debug_only(No_Safepoint_Verifier nsv;) assert_locked_or_safepoint(CodeCache_lock); - NOT_PRODUCT(_has_debug_info = false); - _oops_do_mark_link = NULL; + init_defaults(); _method = method; _entry_bci = InvocationEntryBci; - _osr_link = NULL; - _scavenge_root_link = NULL; - _scavenge_root_state = 0; - _saved_nmethod_link = NULL; - _compiler = NULL; // We have no exception handler or deopt handler make the // values something that will never match a pc like the nmethod vtable entry _exception_offset = 0; _deoptimize_offset = 0; _deoptimize_mh_offset = 0; _orig_pc_offset = 0; -#ifdef HAVE_DTRACE_H - _trap_offset = 0; -#endif // def HAVE_DTRACE_H + _stub_offset = data_offset(); _consts_offset = data_offset(); _oops_offset = data_offset(); @@ -615,17 +626,9 @@ _exception_cache = NULL; _pc_desc_cache.reset_to(NULL); - flags.clear(); - flags.state = alive; - _markedForDeoptimization = 0; - - _lock_count = 0; - _stack_traversal_mark = 0; - code_buffer->copy_oops_to(this); debug_only(verify_scavenge_root_oops()); CodeCache::commit(this); - VTune::create_nmethod(this); } if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) { @@ -673,14 +676,9 @@ debug_only(No_Safepoint_Verifier nsv;) assert_locked_or_safepoint(CodeCache_lock); - NOT_PRODUCT(_has_debug_info = false); - _oops_do_mark_link = NULL; + init_defaults(); _method = method; _entry_bci = InvocationEntryBci; - _osr_link = NULL; - _scavenge_root_link = NULL; - _scavenge_root_state = 0; - _compiler = NULL; // We have no exception handler or deopt handler make the // values something that will never match a pc like the nmethod vtable entry _exception_offset = 0; @@ -706,17 +704,9 @@ _exception_cache = NULL; _pc_desc_cache.reset_to(NULL); - flags.clear(); - flags.state = alive; - _markedForDeoptimization = 0; - - _lock_count = 0; - _stack_traversal_mark = 0; - code_buffer->copy_oops_to(this); debug_only(verify_scavenge_root_oops()); CodeCache::commit(this); - VTune::create_nmethod(this); } if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) { @@ -781,20 +771,13 @@ debug_only(No_Safepoint_Verifier nsv;) assert_locked_or_safepoint(CodeCache_lock); - NOT_PRODUCT(_has_debug_info = false); - _oops_do_mark_link = NULL; + init_defaults(); _method = method; + _entry_bci = entry_bci; _compile_id = compile_id; _comp_level = comp_level; - _entry_bci = entry_bci; - _osr_link = NULL; - _scavenge_root_link = NULL; - _scavenge_root_state = 0; _compiler = compiler; _orig_pc_offset = orig_pc_offset; -#ifdef HAVE_DTRACE_H - _trap_offset = 0; -#endif // def HAVE_DTRACE_H _stub_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start()); // Exception handler and deopt handler are in the stub section @@ -821,15 +804,6 @@ _exception_cache = NULL; _pc_desc_cache.reset_to(scopes_pcs_begin()); - flags.clear(); - flags.state = alive; - _markedForDeoptimization = 0; - - _unload_reported = false; // jvmti state - - _lock_count = 0; - _stack_traversal_mark = 0; - // Copy contents of ScopeDescRecorder to nmethod code_buffer->copy_oops_to(this); debug_info->copy_to(this); @@ -841,8 +815,6 @@ CodeCache::commit(this); - VTune::create_nmethod(this); - // Copy contents of ExceptionHandlerTable to nmethod handler_table->copy_to(this); nul_chk_table->copy_to(this); @@ -988,11 +960,6 @@ } -void nmethod::set_version(int v) { - flags.version = v; -} - - // Promote one word from an assembly-time handle to a live embedded oop. inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) { if (handle == NULL || @@ -1139,6 +1106,8 @@ // This is a private interface with the sweeper. void nmethod::mark_as_seen_on_stack() { assert(is_not_entrant(), "must be a non-entrant method"); + // Set the traversal mark to ensure that the sweeper does 2 + // cleaning passes before moving to zombie. set_stack_traversal_mark(NMethodSweeper::traversal_count()); } @@ -1207,7 +1176,7 @@ // for later on. CodeCache::set_needs_cache_clean(true); } - flags.state = unloaded; + _state = unloaded; // Log the unloading. log_state_change(); @@ -1233,21 +1202,21 @@ if (LogCompilation) { if (xtty != NULL) { ttyLocker ttyl; // keep the following output all in one block - if (flags.state == unloaded) { + if (_state == unloaded) { xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'", os::current_thread_id()); } else { xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s", os::current_thread_id(), - (flags.state == zombie ? " zombie='1'" : "")); + (_state == zombie ? " zombie='1'" : "")); } log_identity(xtty); xtty->stamp(); xtty->end_elem(); } } - if (PrintCompilation && flags.state != unloaded) { - print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant "); + if (PrintCompilation && _state != unloaded) { + print_on(tty, _state == zombie ? "made zombie " : "made not entrant "); tty->cr(); } } @@ -1258,8 +1227,9 @@ bool was_alive = false; - // Make sure the nmethod is not flushed in case of a safepoint in code below. + // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below. nmethodLocker nml(this); + methodHandle the_method(method()); { // If the method is already zombie there is nothing to do @@ -1279,7 +1249,7 @@ // Enter critical section. Does not block for safepoint. MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag); - if (flags.state == state) { + if (_state == state) { // another thread already performed this transition so nothing // to do, but return false to indicate this. return false; @@ -1290,17 +1260,37 @@ if (!is_osr_method() && !is_not_entrant()) { NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), SharedRuntime::get_handle_wrong_method_stub()); - assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, ""); } - was_alive = is_in_use(); // Read state under lock + if (is_in_use()) { + // It's a true state change, so mark the method as decompiled. + // Do it only for transition from alive. + inc_decompile_count(); + } // Change state - flags.state = state; + _state = state; // Log the transition once log_state_change(); + // Remove nmethod from method. + // We need to check if both the _code and _from_compiled_code_entry_point + // refer to this nmethod because there is a race in setting these two fields + // in methodOop as seen in bugid 4947125. + // If the vep() points to the zombie nmethod, the memory for the nmethod + // could be flushed and the compiler and vtable stubs could still call + // through it. + if (method() != NULL && (method()->code() == this || + method()->from_compiled_entry() == verified_entry_point())) { + HandleMark hm; + method()->clear_code(); + } + + if (state == not_entrant) { + mark_as_seen_on_stack(); + } + } // leave critical region under Patching_lock // When the nmethod becomes zombie it is no longer alive so the @@ -1308,18 +1298,17 @@ // state will be flushed later when the transition to zombie // happens or they get unloaded. if (state == zombie) { + // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event + // and it hasn't already been reported for this nmethod then report it now. + // (the event may have been reported earilier if the GC marked it for unloading). + post_compiled_method_unload(); + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); flush_dependencies(NULL); } else { assert(state == not_entrant, "other cases may need to be handled differently"); } - if (state == not_entrant) { - Events::log("Make nmethod not entrant " INTPTR_FORMAT, this); - } else { - Events::log("Make nmethod zombie " INTPTR_FORMAT, this); - } - if (TraceCreateZombies) { tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie"); } @@ -1327,47 +1316,6 @@ // Make sweeper aware that there is a zombie method that needs to be removed NMethodSweeper::notify(this); - // not_entrant only stuff - if (state == not_entrant) { - mark_as_seen_on_stack(); - } - - if (was_alive) { - // It's a true state change, so mark the method as decompiled. - // Do it only for transition from alive. - inc_decompile_count(); - } - - // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event - // and it hasn't already been reported for this nmethod then report it now. - // (the event may have been reported earilier if the GC marked it for unloading). - if (state == zombie) { - post_compiled_method_unload(); - } - - - // Zombie only stuff - if (state == zombie) { - VTune::delete_nmethod(this); - } - - // Check whether method got unloaded at a safepoint before this, - // if so we can skip the flushing steps below - if (method() == NULL) return true; - - // Remove nmethod from method. - // We need to check if both the _code and _from_compiled_code_entry_point - // refer to this nmethod because there is a race in setting these two fields - // in methodOop as seen in bugid 4947125. - // If the vep() points to the zombie nmethod, the memory for the nmethod - // could be flushed and the compiler and vtable stubs could still call - // through it. - if (method()->code() == this || - method()->from_compiled_entry() == verified_entry_point()) { - HandleMark hm; - method()->clear_code(); - } - return true; } @@ -1488,11 +1436,25 @@ moop->signature()->utf8_length(), code_begin(), code_size()); + if (JvmtiExport::should_post_compiled_method_load() || + JvmtiExport::should_post_compiled_method_unload()) { + get_and_cache_jmethod_id(); + } + if (JvmtiExport::should_post_compiled_method_load()) { JvmtiExport::post_compiled_method_load(this); } } +jmethodID nmethod::get_and_cache_jmethod_id() { + if (_jmethod_id == NULL) { + // Cache the jmethod_id since it can no longer be looked up once the + // method itself has been marked for unloading. + _jmethod_id = method()->jmethod_id(); + } + return _jmethod_id; +} + void nmethod::post_compiled_method_unload() { if (unload_reported()) { // During unloading we transition to unloaded and then to zombie @@ -1504,12 +1466,17 @@ DTRACE_METHOD_UNLOAD_PROBE(method()); // If a JVMTI agent has enabled the CompiledMethodUnload event then - // post the event. Sometime later this nmethod will be made a zombie by - // the sweeper but the methodOop will not be valid at that point. - if (JvmtiExport::should_post_compiled_method_unload()) { + // post the event. Sometime later this nmethod will be made a zombie + // by the sweeper but the methodOop will not be valid at that point. + // If the _jmethod_id is null then no load event was ever requested + // so don't bother posting the unload. The main reason for this is + // that the jmethodID is a weak reference to the methodOop so if + // it's being unloaded there's no way to look it up since the weak + // ref will have been cleared. + if (_jmethod_id != NULL && JvmtiExport::should_post_compiled_method_unload()) { assert(!unload_reported(), "already unloaded"); HandleMark hm; - JvmtiExport::post_compiled_method_unload(method()->jmethod_id(), code_begin()); + JvmtiExport::post_compiled_method_unload(_jmethod_id, code_begin()); } // The JVMTI CompiledMethodUnload event can be enabled or disabled at @@ -2087,7 +2054,6 @@ void nmethod_init() { // make sure you didn't forget to adjust the filler fields - assert(sizeof(nmFlags) <= 4, "nmFlags occupies more than a word"); assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word"); } @@ -2323,7 +2289,6 @@ tty->print("((nmethod*) "INTPTR_FORMAT ") ", this); tty->print(" for method " INTPTR_FORMAT , (address)method()); tty->print(" { "); - if (version()) tty->print("v%d ", version()); if (is_in_use()) tty->print("in_use "); if (is_not_entrant()) tty->print("not_entrant "); if (is_zombie()) tty->print("zombie "); @@ -2659,13 +2624,10 @@ case Bytecodes::_getstatic: case Bytecodes::_putstatic: { - methodHandle sdm = sd->method(); - Bytecode_field* field = Bytecode_field_at(sdm(), sdm->bcp_from(sd->bci())); - constantPoolOop sdmc = sdm->constants(); - symbolOop name = sdmc->name_ref_at(field->index()); + Bytecode_field* field = Bytecode_field_at(sd->method(), sd->bci()); st->print(" "); - if (name != NULL) - name->print_symbol_on(st); + if (field->name() != NULL) + field->name()->print_symbol_on(st); else st->print("<UNKNOWN>"); }
--- a/hotspot/src/share/vm/code/nmethod.hpp Fri Jul 30 22:43:50 2010 +0100 +++ b/hotspot/src/share/vm/code/nmethod.hpp Sat Jul 31 15:10:59 2010 +0100 @@ -78,29 +78,8 @@ // nmethods (native methods) are the compiled code versions of Java methods. - -struct nmFlags { - friend class VMStructs; - unsigned int version:8; // version number (0 = first version) - unsigned int age:4; // age (in # of sweep steps) - - unsigned int state:2; // {alive, zombie, unloaded) - - unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap? - unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures - unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies - unsigned int markedForReclamation:1; // Used by NMethodSweeper - - unsigned int has_unsafe_access:1; // May fault due to unsafe access. - unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes? - - unsigned int speculatively_disconnected:1; // Marked for potential unload - - void clear(); -}; - - -// A nmethod contains: +// +// An nmethod contains: // - header (the nmethod structure) // [Relocation] // - relocation information @@ -131,10 +110,9 @@ friend class CodeCache; // non-perm oops private: // Shared fields for all nmethod's - static int _zombie_instruction_size;