OpenJDK / jdk / jdk
changeset 8517:c00233c30967
Merge
author | lana |
---|---|
date | Sun, 06 Mar 2011 20:32:49 -0800 |
parents | 3406d5bc0ae2 08bfaed69cac |
children | 01dd5b93b2a7 b8b7c54b0c7a |
files | hotspot/make/windows/platform_amd64 hotspot/make/windows/platform_i486 hotspot/make/windows/platform_ia64 hotspot/src/share/tools/ProjectCreator/Macro.java hotspot/src/share/tools/ProjectCreator/MacroDefinitions.java jdk/src/share/classes/java/dyn/NoAccessException.java jdk/src/share/classes/java/dyn/Switcher.java jdk/test/java/lang/Thread/StopBeforeStart.java |
diffstat | 329 files changed, 8755 insertions(+), 4272 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Tue Mar 01 15:24:46 2011 +0300 +++ b/.hgtags Sun Mar 06 20:32:49 2011 -0800 @@ -105,3 +105,4 @@ 7da3f5f30855dec6bf3a86529e87dee883b90c72 jdk7-b128 6823ea7eb8eb6fab405d7edb7a5c2f690887a2fa jdk7-b129 a36beda9b9de91231d92a2c529f21cc218fcf8d5 jdk7-b130 +d8af56da89bc0fc02a6b6ad78f51157a46d665ab jdk7-b131
--- a/.hgtags-top-repo Tue Mar 01 15:24:46 2011 +0300 +++ b/.hgtags-top-repo Sun Mar 06 20:32:49 2011 -0800 @@ -105,3 +105,4 @@ 57d702105b23fb90e40beaf00f8f8aeae5e249e7 jdk7-b128 a6b015b59fbc2518762c17ccc35702f03ef7713a jdk7-b129 cc58c11af15411042719e9c82707fdbef60a9e0f jdk7-b130 +5d86d951426aaf340b1ba84ae2d5ab5da65a71e2 jdk7-b131
--- a/corba/.hgtags Tue Mar 01 15:24:46 2011 +0300 +++ b/corba/.hgtags Sun Mar 06 20:32:49 2011 -0800 @@ -105,3 +105,4 @@ 9baa8f94a11d6c5cab3f9f0e5a20106326d0932e jdk7-b128 66fa0fcc779296c99746b09efce6109944f82f30 jdk7-b129 563a8f8b5be3940e9346cffac4eff9ed02b3c69f jdk7-b130 +9d6dd2cdfcb92612dbd836ecded87770d52b49db jdk7-b131
--- a/hotspot/.hgtags Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/.hgtags Sun Mar 06 20:32:49 2011 -0800 @@ -149,3 +149,5 @@ ae4b185f2ed14af7bab610738c333840598cdcc4 jdk7-b129 ae4b185f2ed14af7bab610738c333840598cdcc4 hs21-b01 e9aa2ca89ad6c53420623d579765f9706ec523d7 jdk7-b130 +0aa3b49089112d5faa77902ad680c582ab53f651 jdk7-b131 +e9aa2ca89ad6c53420623d579765f9706ec523d7 hs21-b02
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,8 +31,7 @@ /** Very minimal port for now to get frames working */ public class StubRoutines { - private static AddressField callStubReturnAddressField; - private static AddressField callStubCompiledReturnAddressField; + private static AddressField callStubReturnAddressField; static { VM.registerVMInitializedObserver(new Observer() { @@ -44,20 +43,7 @@ private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("StubRoutines"); - callStubReturnAddressField = type.getAddressField("_call_stub_return_address"); - // Only some platforms have specific return from compiled to call_stub - try { - type = db.lookupType("StubRoutines::x86"); - if (type != null) { - callStubCompiledReturnAddressField = type.getAddressField("_call_stub_compiled_return"); - } - } catch (RuntimeException re) { - callStubCompiledReturnAddressField = null; - } - if (callStubCompiledReturnAddressField == null && VM.getVM().getCPU().equals("x86")) { - throw new InternalError("Missing definition for _call_stub_compiled_return"); - } } public StubRoutines() { @@ -65,20 +51,10 @@ public boolean returnsToCallStub(Address returnPC) { Address addr = callStubReturnAddressField.getValue(); - boolean result = false; - if (addr == null) { - result = (addr == returnPC); - } else { - result = addr.equals(returnPC); - } - if (result || callStubCompiledReturnAddressField == null ) return result; - // Could be a return to compiled code return point - addr = callStubCompiledReturnAddressField.getValue(); if (addr == null) { return (addr == returnPC); } else { return (addr.equals(returnPC)); } - } }
--- a/hotspot/make/Makefile Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/make/Makefile Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ # ALT_OUTPUTDIR Output directory to use for hotspot build # ALT_EXPORT_PATH Directory to export hotspot build to # ALT_JDK_IMPORT_PATH Current JDK build (only for create_jdk rules) +# ALT_JDK_TARGET_IMPORT_PATH Current JDK build when cross-compiling # ALT_BUILD_WIN_SA Building SA on Windows is disabled by default. # Set ALT_BUILD_WIN_SA=1 to enable building SA on # Windows.
--- a/hotspot/make/defs.make Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/make/defs.make Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -162,6 +162,13 @@ JDK_IMPORT_PATH=$(ALT_JDK_IMPORT_PATH) endif +# Other parts of JDK build may require an import JDK that can be executed +# on the build host. For cross-compile builds we also need an import JDK +# that matches the target arch, so for that we set ALT_JDK_TARGET_IMPORT_PATH +ifneq ($(ALT_JDK_TARGET_IMPORT_PATH),) + JDK_IMPORT_PATH=$(ALT_JDK_TARGET_IMPORT_PATH) +endif + # Find JDK used for javac compiles BOOTDIR=$(SLASH_JAVA)/re/j2se/$(PREVIOUS_JDK_VERSION)/latest/binaries/$(PLATFORM) ifneq ($(ALT_BOOTDIR),)
--- a/hotspot/make/hotspot_version Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/make/hotspot_version Sun Mar 06 20:32:49 2011 -0800 @@ -35,7 +35,7 @@ HS_MAJOR_VER=21 HS_MINOR_VER=0 -HS_BUILD_NUMBER=02 +HS_BUILD_NUMBER=03 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/hotspot/make/jprt.properties Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/make/jprt.properties Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -437,6 +437,7 @@ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_CMS, \ + ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_G1, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \
--- a/hotspot/make/windows/create.bat Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/make/windows/create.bat Sun Mar 06 20:32:49 2011 -0800 @@ -1,6 +1,6 @@ @echo off REM -REM Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +REM Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. REM REM This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,7 @@ :testit -cl 2>&1 | grep "IA-64" >NUL -if %errorlevel% == 0 goto isia64 -cl 2>&1 | grep "AMD64" >NUL +cl 2>&1 | grep "x64" >NUL if %errorlevel% == 0 goto amd64 set ARCH=x86 set BUILDARCH=i486 @@ -64,12 +62,6 @@ set BUILDARCH=amd64 set Platform_arch=x86 set Platform_arch_model=x86_64 -goto done -:isia64 -set ARCH=ia64 -set BUILDARCH=ia64 -set Platform_arch=ia64 -set Platform_arch_model=ia64 :done setlocal @@ -81,7 +73,7 @@ REM Set HotSpotWorkSpace to the directy two steps above this script for %%i in ("%~dp0..") do ( set HotSpotWorkSpace=%%~dpi) set HotSpotBuildRoot=%HotSpotWorkSpace%build -set HotSpotBuildSpace=%HotSpotBuildRoot%\vs +set HotSpotBuildSpace=%HotSpotBuildRoot%\vs-%BUILDARCH% set HotSpotJDKDist=%1 @@ -89,9 +81,9 @@ for /F %%i in ('sh %HotSpotWorkSpace%/make/windows/get_msc_ver.sh') do set %%i echo ************************************************************** -set ProjectFile=jvm.vcproj +set ProjectFile=%HotSpotBuildSpace%\jvm.vcproj if "%MSC_VER%" == "1200" ( -set ProjectFile=jvm.dsp +set ProjectFile=%HotSpotBuildSpace%\jvm.dsp echo Will generate VC6 project {unsupported} ) else ( if "%MSC_VER%" == "1400" ( @@ -163,7 +155,7 @@ ) REM force regneration of ProjectFile -if exist %HotSpotBuildSpace%\%ProjectFile% del %HotSpotBuildSpace%\%ProjectFile% +if exist %ProjectFile% del %ProjectFile% for /D %%i in (compiler1, compiler2, tiered, core, kernel) do ( echo -- %%i -- @@ -182,6 +174,7 @@ echo BUILDARCH=%BUILDARCH% >> %HotSpotBuildSpace%\%%i\local.make echo Platform_arch=%Platform_arch% >> %HotSpotBuildSpace%\%%i\local.make echo Platform_arch_model=%Platform_arch_model% >> %HotSpotBuildSpace%\%%i\local.make +echo MSC_VER=%MSC_VER% >> %HotSpotBuildSpace%\%%i\local.make for /D %%j in (debug, fastdebug, product) do ( if NOT EXIST %HotSpotBuildSpace%\%%i\%%j mkdir %HotSpotBuildSpace%\%%i\%%j @@ -196,7 +189,7 @@ pushd %HotSpotBuildRoot% REM It doesn't matter which variant we use here, "compiler1" is as good as any of the others - we need the common variables -nmake /nologo /F %HotSpotWorkSpace%/make/windows/projectfiles/common/Makefile LOCAL_MAKE=%HotSpotBuildSpace%\compiler1\local.make %HotSpotBuildRoot%/%ProjectFile% +nmake /nologo /F %HotSpotWorkSpace%/make/windows/projectfiles/common/Makefile LOCAL_MAKE=%HotSpotBuildSpace%\compiler1\local.make %ProjectFile% popd
--- a/hotspot/make/windows/makefiles/compile.make Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/make/windows/makefiles/compile.make Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -141,9 +141,6 @@ !endif !endif -# Add what version of the compiler we think this is to the compile line -CPP_FLAGS=$(CPP_FLAGS) /D "MSC_VER=$(MSC_VER)" - # By default, we do not want to use the debug version of the msvcrt.dll file # but if MFC_DEBUG is defined in the environment it will be used. MS_RUNTIME_OPTION = /MD
--- a/hotspot/make/windows/makefiles/projectcreator.make Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/make/windows/makefiles/projectcreator.make Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -36,8 +36,6 @@ $(WorkSpace)\src\share\tools\ProjectCreator\DirectoryTree.java \ $(WorkSpace)\src\share\tools\ProjectCreator\DirectoryTreeNode.java \ $(WorkSpace)\src\share\tools\ProjectCreator\FileFormatException.java \ - $(WorkSpace)\src\share\tools\ProjectCreator\Macro.java \ - $(WorkSpace)\src\share\tools\ProjectCreator\MacroDefinitions.java \ $(WorkSpace)\src\share\tools\ProjectCreator\ProjectCreator.java \ $(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatform.java \ $(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC6.java \ @@ -50,6 +48,10 @@ # This is only used internally ProjectCreatorIncludesPRIVATE=\ + -relativeInclude src\closed\share\vm \ + -relativeInclude src\closed\os\windows\vm \ + -relativeInclude src\closed\os_cpu\windows_$(Platform_arch)\vm \ + -relativeInclude src\closed\cpu\$(Platform_arch)\vm \ -relativeInclude src\share\vm \ -relativeInclude src\share\vm\prims \ -relativeInclude src\os\windows\vm \ @@ -84,7 +86,7 @@ -buildBase $(HOTSPOTBUILDSPACE)\%f\%b \ -startAt src \ -compiler $(VcVersion) \ - -projectFileName $(HOTSPOTBUILDROOT)\$(ProjectFile) \ + -projectFileName $(HOTSPOTBUILDSPACE)\$(ProjectFile) \ -jdkTargetRoot $(HOTSPOTJDKDIST) \ -define ALIGN_STACK_FRAMES \ -define VM_LITTLE_ENDIAN \ @@ -106,13 +108,20 @@ # Add in build-specific options !if "$(BUILDARCH)" == "i486" ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ + -platformName Win32 \ -define IA32 \ -ignorePath x86_64 \ -define TARGET_ARCH_MODEL_x86_32 !else +!if "$(BUILDARCH)" == "amd64" ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ + -platformName x64 \ + -define AMD64 \ + -define _LP64 \ -ignorePath x86_32 \ - -define TARGET_ARCH_MODEL_x86_64 + -define TARGET_ARCH_MODEL_x86_64 \ + -define TARGET_OS_ARCH_MODEL_windows_x86_64 +!endif !endif ProjectCreatorIDEOptionsIgnoreCompiler1=\
--- a/hotspot/make/windows/makefiles/rules.make Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/make/windows/makefiles/rules.make Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ !if "$(MSC_VER)" == "1200" VcVersion=VC6 -ProjectFile=vm.dsp +ProjectFile=jvm.dsp !elseif "$(MSC_VER)" == "1400"
--- a/hotspot/make/windows/platform_amd64 Tue Mar 01 15:24:46 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -// Platform file for win32 NT platform - -os_family = windows - -arch = x86 - -arch_model = x86_64 - -os_arch = windows_x86 - -os_arch_model = windows_x86_64 - -lib_arch = amd64 - -compiler = visCPP
--- a/hotspot/make/windows/platform_i486 Tue Mar 01 15:24:46 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -// Platform file for windows platform - -os_family = windows - -arch = x86 - -arch_model = x86_32 - -os_arch = windows_x86 - -os_arch_model = windows_x86_32 - -lib_arch = i386 - -compiler = visCPP
--- a/hotspot/make/windows/platform_ia64 Tue Mar 01 15:24:46 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -// Platform file for Itanium Windows platform $Revision: 1.0 $ - -os_family = win32 - -arch = ia64 - -os_arch = win32_ia64 - -compiler = visCPP - -gnu_dis_arch = ia64 -
--- a/hotspot/make/windows/projectfiles/common/Makefile Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/make/windows/projectfiles/common/Makefile Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -54,8 +54,6 @@ JvmtiOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\jvmtifiles !include $(HOTSPOTWORKSPACE)/make/windows/makefiles/jvmti.make -Platform=$(HOTSPOTWORKSPACE)/make/windows/platform_$(BUILDARCH) - !if "$(Variant)" == "compiler2" # Pick up rules for building adlc !include $(HOTSPOTWORKSPACE)/make/windows/makefiles/adlc.make @@ -105,17 +103,16 @@ !endif ProjectCreatorIDEOptions = $(ProjectCreatorIDEOptions) \ - -platform $(Platform) \ -define HOTSPOT_RELEASE_VERSION=\\\"$(HOTSPOT_RELEASE_VERSION)\\\" \ -define JRE_RELEASE_VERSION=\\\"$(JRE_RELEASE_VERSION)\\\" \ -define HOTSPOT_VM_DISTRO=\\\"$(HOTSPOT_VM_DISTRO)\\\" -$(HOTSPOTBUILDROOT)/$(ProjectFile): $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class +$(HOTSPOTBUILDSPACE)/$(ProjectFile): $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class @$(RUN_JAVA) -Djava.class.path=$(HOTSPOTBUILDSPACE)/classes ProjectCreator WinGammaPlatform$(VcVersion) $(ProjectCreatorIDEOptions) clean: @rm -rf $(HOTSPOTBUILDSPACE)/classes - @rm -r ../$(ProjectFile) + @rm -r $(HOTSPOTBUILDSPACE)/$(ProjectFile) $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class: $(ProjectCreatorSources) @if exist $(HOTSPOTBUILDSPACE)\classes rmdir /s /q $(HOTSPOTBUILDSPACE)\classes
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -2407,14 +2407,23 @@ #endif -void MacroAssembler::load_sized_value(Address src, Register dst, - size_t size_in_bytes, bool is_signed) { +void MacroAssembler::load_sized_value(Address src, Register dst, size_t size_in_bytes, bool is_signed) { switch (size_in_bytes) { - case 8: ldx(src, dst); break; - case 4: ld( src, dst); break; - case 2: is_signed ? ldsh(src, dst) : lduh(src, dst); break; - case 1: is_signed ? ldsb(src, dst) : ldub(src, dst); break; - default: ShouldNotReachHere(); + case 8: ld_long(src, dst); break; + case 4: ld( src, dst); break; + case 2: is_signed ? ldsh(src, dst) : lduh(src, dst); break; + case 1: is_signed ? ldsb(src, dst) : ldub(src, dst); break; + default: ShouldNotReachHere(); + } +} + +void MacroAssembler::store_sized_value(Register src, Address dst, size_t size_in_bytes) { + switch (size_in_bytes) { + case 8: st_long(src, dst); break; + case 4: st( src, dst); break; + case 2: sth( src, dst); break; + case 1: stb( src, dst); break; + default: ShouldNotReachHere(); } }
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -2330,8 +2330,9 @@ void lcmp( Register Ra, Register Rb, Register Rresult); #endif - // Loading values by size and signed-ness - void load_sized_value(Address src, Register dst, size_t size_in_bytes, bool is_signed); + // Load and store values by size and signed-ness + void load_sized_value( Address src, Register dst, size_t size_in_bytes, bool is_signed); + void store_sized_value(Register src, Address dst, size_t size_in_bytes); void float_cmp( bool is_float, int unordered_result, FloatRegister Fa, FloatRegister Fb,
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -596,16 +596,9 @@ __ st_ptr(O1_scratch, Address(O0_argslot, 0)); } else { Address prim_value_addr(O1_scratch, java_lang_boxing_object::value_offset_in_bytes(arg_type)); - __ load_sized_value(prim_value_addr, O2_scratch, type2aelembytes(arg_type), is_signed_subword_type(arg_type)); - if (arg_slots == 2) { - __ unimplemented("not yet tested"); -#ifndef _LP64 - __ signx(O2_scratch, O3_scratch); // Sign extend -#endif - __ st_long(O2_scratch, Address(O0_argslot, 0)); // Uses O2/O3 on !_LP64 - } else { - __ st_ptr( O2_scratch, Address(O0_argslot, 0)); - } + const int arg_size = type2aelembytes(arg_type); + __ load_sized_value(prim_value_addr, O2_scratch, arg_size, is_signed_subword_type(arg_type)); + __ store_sized_value(O2_scratch, Address(O0_argslot, 0), arg_size); // long store uses O2/O3 on !_LP64 } if (direct_to_method) { @@ -784,11 +777,9 @@ switch (ek) { case _adapter_opt_i2l: { - __ ldsw(arg_lsw, O2_scratch); // Load LSW -#ifndef _LP64 - __ signx(O2_scratch, O3_scratch); // Sign extend -#endif - __ st_long(O2_scratch, arg_msw); // Uses O2/O3 on !_LP64 + __ ldsw(arg_lsw, O2_scratch); // Load LSW + NOT_LP64(__ srlx(O2_scratch, BitsPerInt, O3_scratch)); // Move high bits to lower bits for std + __ st_long(O2_scratch, arg_msw); // Uses O2/O3 on !_LP64 } break; case _adapter_opt_unboxl:
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Sun Mar 06 20:32:49 2011 -0800 @@ -8125,6 +8125,17 @@ %} #endif +instruct cmpLTMask0( iRegI dst, iRegI src, immI0 zero, flagsReg ccr ) %{ + match(Set dst (CmpLTMask src zero)); + effect(KILL ccr); + size(4); + format %{ "SRA $src,#31,$dst\t# cmpLTMask0" %} + ins_encode %{ + __ sra($src$$Register, 31, $dst$$Register); + %} + ins_pipe(ialu_reg_imm); +%} + instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{ match(Set dst (CmpLTMask p q)); effect( KILL ccr ); @@ -8144,19 +8155,7 @@ format %{ "SUBcc $p,$q,$p\t! p' = p-q\n\t" "ADD $p,$y,$tmp\t! g3=p-q+y\n\t" - "MOVl $tmp,$p\t! p' < 0 ? p'+y : p'" %} - ins_encode( enc_cadd_cmpLTMask(p, q, y, tmp) ); - ins_pipe( cadd_cmpltmask ); -%} - -instruct cadd_cmpLTMask2( iRegI p, iRegI q, iRegI y, iRegI tmp, flagsReg ccr ) %{ - match(Set p (AddI (SubI p q) (AndI (CmpLTMask p q) y))); - effect( KILL ccr, TEMP tmp); - ins_cost(DEFAULT_COST*3); - - format %{ "SUBcc $p,$q,$p\t! p' = p-q\n\t" - "ADD $p,$y,$tmp\t! g3=p-q+y\n\t" - "MOVl $tmp,$p\t! p' < 0 ? p'+y : p'" %} + "MOVlt $tmp,$p\t! p' < 0 ? p'+y : p'" %} ins_encode( enc_cadd_cmpLTMask(p, q, y, tmp) ); ins_pipe( cadd_cmpltmask ); %}
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -2349,6 +2349,17 @@ a_byte(p); } +void Assembler::por(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + + emit_byte(0x66); + int encode = prefix_and_encode(dst->encoding(), src->encoding()); + emit_byte(0x0F); + + emit_byte(0xEB); + emit_byte(0xC0 | encode); +} + void Assembler::pshufd(XMMRegister dst, XMMRegister src, int mode) { assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); @@ -6528,20 +6539,39 @@ return off; } -void MacroAssembler::load_sized_value(Register dst, Address src, - size_t size_in_bytes, bool is_signed) { +void MacroAssembler::load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2) { switch (size_in_bytes) { #ifndef _LP64 - // For case 8, caller is responsible for manually loading - // the second word into another register. - case 8: movl(dst, src); break; + case 8: + assert(dst2 != noreg, "second dest register required"); + movl(dst, src); + movl(dst2, src.plus_disp(BytesPerInt)); + break; #else - case 8: movq(dst, src); break; + case 8: movq(dst, src); break; #endif - case 4: movl(dst, src); break; - case 2: is_signed ? load_signed_short(dst, src) : load_unsigned_short(dst, src); break; - case 1: is_signed ? load_signed_byte( dst, src) : load_unsigned_byte( dst, src); break; - default: ShouldNotReachHere(); + case 4: movl(dst, src); break; + case 2: is_signed ? load_signed_short(dst, src) : load_unsigned_short(dst, src); break; + case 1: is_signed ? load_signed_byte( dst, src) : load_unsigned_byte( dst, src); break; + default: ShouldNotReachHere(); + } +} + +void MacroAssembler::store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2) { + switch (size_in_bytes) { +#ifndef _LP64 + case 8: + assert(src2 != noreg, "second source register required"); + movl(dst, src); + movl(dst.plus_disp(BytesPerInt), src2); + break; +#else + case 8: movq(dst, src); break; +#endif + case 4: movl(dst, src); break; + case 2: movw(dst, src); break; + case 1: movb(dst, src); break; + default: ShouldNotReachHere(); } } @@ -8636,7 +8666,7 @@ // Compare strings. void MacroAssembler::string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register result, - XMMRegister vec1, XMMRegister vec2) { + XMMRegister vec1) { Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL; // Compute the minimum of the string lengths and the @@ -8683,62 +8713,85 @@ bind(LSkip2); } - // Advance to next character - addptr(str1, 2); - addptr(str2, 2); + Address::ScaleFactor scale = Address::times_2; + int stride = 8; + + // Advance to next element + addptr(str1, 16/stride); + addptr(str2, 16/stride); if (UseSSE42Intrinsics) { - // With SSE4.2, use double quad vector compare - Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; + Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; + int pcmpmask = 0x19; // Setup to compare 16-byte vectors - movl(cnt1, cnt2); - andl(cnt2, 0xfffffff8); // cnt2 holds the vector count - andl(cnt1, 0x00000007); // cnt1 holds the tail count - testl(cnt2, cnt2); + movl(result, cnt2); + andl(cnt2, ~(stride - 1)); // cnt2 holds the vector count jccb(Assembler::zero, COMPARE_TAIL); - lea(str2, Address(str2, cnt2, Address::times_2)); - lea(str1, Address(str1, cnt2, Address::times_2)); - negptr(cnt2); - - bind(COMPARE_VECTORS); - movdqu(vec1, Address(str1, cnt2, Address::times_2)); - movdqu(vec2, Address(str2, cnt2, Address::times_2)); - pxor(vec1, vec2); - ptest(vec1, vec1); - jccb(Assembler::notZero, VECTOR_NOT_EQUAL); - addptr(cnt2, 8); - jcc(Assembler::notZero, COMPARE_VECTORS); - jmpb(COMPARE_TAIL); + lea(str1, Address(str1, result, scale)); + lea(str2, Address(str2, result, scale)); + negptr(result); + + // pcmpestri + // inputs: + // vec1- substring + // rax - negative string length (elements count) + // mem - scaned string + // rdx - string length (elements count) + // pcmpmask - cmp mode: 11000 (string compare with negated result) + // + 00 (unsigned bytes) or + 01 (unsigned shorts) + // outputs: + // rcx - first mismatched element index + assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri"); + + bind(COMPARE_WIDE_VECTORS); + movdqu(vec1, Address(str1, result, scale)); + pcmpestri(vec1, Address(str2, result, scale), pcmpmask); + // After pcmpestri cnt1(rcx) contains mismatched element index + + jccb(Assembler::below, VECTOR_NOT_EQUAL); // CF==1 + addptr(result, stride); + subptr(cnt2, stride); + jccb(Assembler::notZero, COMPARE_WIDE_VECTORS); + + // compare wide vectors tail + testl(result, result); + jccb(Assembler::zero, LENGTH_DIFF_LABEL); + + movl(cnt2, stride); + movl(result, stride); + negptr(result); + movdqu(vec1, Address(str1, result, scale)); + pcmpestri(vec1, Address(str2, result, scale), pcmpmask); + jccb(Assembler::aboveEqual, LENGTH_DIFF_LABEL); // Mismatched characters in the vectors bind(VECTOR_NOT_EQUAL); - lea(str1, Address(str1, cnt2, Address::times_2)); - lea(str2, Address(str2, cnt2, Address::times_2)); - movl(cnt1, 8); - - // Compare tail (< 8 chars), or rescan last vectors to - // find 1st mismatched characters - bind(COMPARE_TAIL); - testl(cnt1, cnt1); - jccb(Assembler::zero, LENGTH_DIFF_LABEL); - movl(cnt2, cnt1); + addptr(result, cnt1); + movptr(cnt2, result); + load_unsigned_short(result, Address(str1, cnt2, scale)); + load_unsigned_short(cnt1, Address(str2, cnt2, scale)); + subl(result, cnt1); + jmpb(POP_LABEL); + + bind(COMPARE_TAIL); // limit is zero + movl(cnt2, result); // Fallthru to tail compare } // Shift str2 and str1 to the end of the arrays, negate min - lea(str1, Address(str1, cnt2, Address::times_2, 0)); - lea(str2, Address(str2, cnt2, Address::times_2, 0)); + lea(str1, Address(str1, cnt2, scale, 0)); + lea(str2, Address(str2, cnt2, scale, 0)); negptr(cnt2); - // Compare the rest of the characters + // Compare the rest of the elements bind(WHILE_HEAD_LABEL); - load_unsigned_short(result, Address(str1, cnt2, Address::times_2, 0)); - load_unsigned_short(cnt1, Address(str2, cnt2, Address::times_2, 0)); + load_unsigned_short(result, Address(str1, cnt2, scale, 0)); + load_unsigned_short(cnt1, Address(str2, cnt2, scale, 0)); subl(result, cnt1); jccb(Assembler::notZero, POP_LABEL); increment(cnt2); - jcc(Assembler::notZero, WHILE_HEAD_LABEL); + jccb(Assembler::notZero, WHILE_HEAD_LABEL); // Strings are equal up to min length. Return the length difference. bind(LENGTH_DIFF_LABEL); @@ -8747,7 +8800,7 @@ // Discard the stored length difference bind(POP_LABEL); - addptr(rsp, wordSize); + pop(cnt1); // That's it bind(DONE_LABEL); @@ -8795,6 +8848,7 @@ if (UseSSE42Intrinsics) { // With SSE4.2, use double quad vector compare Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; + // Compare 16-byte vectors andl(result, 0x0000000e); // tail count (in bytes) andl(limit, 0xfffffff0); // vector count (in bytes) @@ -8808,11 +8862,23 @@ movdqu(vec1, Address(ary1, limit, Address::times_1)); movdqu(vec2, Address(ary2, limit, Address::times_1)); pxor(vec1, vec2); + ptest(vec1, vec1); jccb(Assembler::notZero, FALSE_LABEL); addptr(limit, 16); jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); + testl(result, result); + jccb(Assembler::zero, TRUE_LABEL); + + movdqu(vec1, Address(ary1, result, Address::times_1, -16)); + movdqu(vec2, Address(ary2, result, Address::times_1, -16)); + pxor(vec1, vec2); + + ptest(vec1, vec1); + jccb(Assembler::notZero, FALSE_LABEL); + jmpb(TRUE_LABEL); + bind(COMPARE_TAIL); // limit is zero movl(limit, result); // Fallthru to tail compare
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1277,6 +1277,9 @@ void prefetcht2(Address src); void prefetchw(Address src); + // POR - Bitwise logical OR + void por(XMMRegister dst, XMMRegister src); + // Shuffle Packed Doublewords void pshufd(XMMRegister dst, XMMRegister src, int mode); void pshufd(XMMRegister dst, Address src, int mode); @@ -1522,8 +1525,9 @@ // Support for sign-extension (hi:lo = extend_sign(lo)) void extend_sign(Register hi, Register lo); - // Loading values by size and signed-ness - void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed); + // Load and store values by size and signed-ness + void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2 = noreg); + void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg); // Support for inc/dec with optimal instruction selection depending on value @@ -2293,7 +2297,7 @@ // Compare strings. void string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register result, - XMMRegister vec1, XMMRegister vec2); + XMMRegister vec1); // Compare char[] arrays. void char_arrays_equals(bool is_array_equ, Register ary1, Register ary2,
--- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1899,8 +1899,6 @@ Label do_double; Label done_conv; - address compiled_entry = __ pc(); - // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases if (UseSSE < 2) { __ lea(state, Address(rbp, -(int)sizeof(BytecodeInterpreter))); @@ -1934,15 +1932,7 @@ __ jmp(done_conv); } -#if 0 - // emit a sentinel we can test for when converting an interpreter - // entry point to a compiled entry point. - __ a_long(Interpreter::return_sentinel); - __ a_long((int)compiled_entry); -#endif - // Return point to interpreter from compiled/native method - InternalAddress return_from_native_method(__ pc()); __ bind(done_conv);
--- a/hotspot/src/cpu/x86/vm/interpreter_x86.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/interpreter_x86.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,14 +26,6 @@ #define CPU_X86_VM_INTERPRETER_X86_HPP public: - - // Sentinel placed in the code for interpreter returns so - // that i2c adapters and osr code can recognize an interpreter - // return address and convert the return to a specialized - // block of code to handle compiedl return values and cleaning - // the fpu stack. - static const int return_sentinel; - static Address::ScaleFactor stackElementScale() { return Address::times_4; } // Offset from rsp (which points to the last stack element)
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,6 @@ #define __ _masm-> -// Initialize the sentinel used to distinguish an interpreter return address. -const int Interpreter::return_sentinel = 0xfeedbeed; - //------------------------------------------------------------------------------------------------------------------------ address AbstractInterpreterGenerator::generate_slow_signature_handler() {
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -602,24 +602,18 @@ // make room for the new argument: __ movl(rax_argslot, rcx_bmh_vmargslot); __ lea(rax_argslot, __ argument_address(rax_argslot)); - insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask, - rax_argslot, rbx_temp, rdx_temp); + + insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask, rax_argslot, rbx_temp, rdx_temp); // store bound argument into the new stack slot: __ load_heap_oop(rbx_temp, rcx_bmh_argument); - Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type)); if (arg_type == T_OBJECT) { __ movptr(Address(rax_argslot, 0), rbx_temp); } else { - __ load_sized_value(rdx_temp, prim_value_addr, - type2aelembytes(arg_type), is_signed_subword_type(arg_type)); - __ movptr(Address(rax_argslot, 0), rdx_temp); -#ifndef _LP64 - if (arg_slots == 2) { - __ movl(rdx_temp, prim_value_addr.plus_disp(wordSize)); - __ movl(Address(rax_argslot, Interpreter::stackElementSize), rdx_temp); - } -#endif //_LP64 + Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type)); + const int arg_size = type2aelembytes(arg_type); + __ load_sized_value(rdx_temp, prim_value_addr, arg_size, is_signed_subword_type(arg_type), rbx_temp); + __ store_sized_value(Address(rax_argslot, 0), rdx_temp, arg_size, rbx_temp); } if (direct_to_method) {
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -660,25 +660,6 @@ int comp_args_on_stack, const BasicType *sig_bt, const VMRegPair *regs) { - // we're being called from the interpreter but need to find the - // compiled return entry point. The return address on the stack - // should point at it and we just need to pull the old value out. - // load up the pointer to the compiled return entry point and - // rewrite our return pc. The code is arranged like so: - // - // .word Interpreter::return_sentinel - // .word address_of_compiled_return_point - // return_entry_point: blah_blah_blah - // - // So we can find the appropriate return point by loading up the word - // just prior to the current return address we have on the stack. - // - // We will only enter here from an interpreted frame and never from after - // passing thru a c2i. Azul allowed this but we do not. If we lose the - // race and use a c2i we will remain interpreted for the race loser(s). - // This removes all sorts of headaches on the x86 side and also eliminates - // the possibility of having c2i -> i2c -> c2i -> ... endless transitions. - // Note: rsi contains the senderSP on entry. We must preserve it since // we may do a i2c -> c2i transition if we lose a race where compiled @@ -687,40 +668,6 @@ // Pick up the return address __ movptr(rax, Address(rsp, 0)); - // If UseSSE >= 2 then no cleanup is needed on the return to the - // interpreter so skip fixing up the return entry point unless - // VerifyFPU is enabled. - if (UseSSE < 2 || VerifyFPU) { - Label skip, chk_int; - // If we were called from the call stub we need to do a little bit different - // cleanup than if the interpreter returned to the call stub. - - ExternalAddress stub_return_address(StubRoutines::_call_stub_return_address); - __ cmpptr(rax, stub_return_address.addr()); - __ jcc(Assembler::notEqual, chk_int); - assert(StubRoutines::x86::get_call_stub_compiled_return() != NULL, "must be set"); - __ lea(rax, ExternalAddress(StubRoutines::x86::get_call_stub_compiled_return())); - __ jmp(skip); - - // It must be the interpreter since we never get here via a c2i (unlike Azul) - - __ bind(chk_int); -#ifdef ASSERT - { - Label ok; - __ cmpl(Address(rax, -2*wordSize), Interpreter::return_sentinel); - __ jcc(Assembler::equal, ok); - __ int3(); - __ bind(ok); - } -#endif // ASSERT - __ movptr(rax, Address(rax, -wordSize)); - __ bind(skip); - } - - // rax, now contains the compiled return entry point which will do an - // cleanup needed for the return from compiled to interpreted. - // Must preserve original SP for loading incoming arguments because // we need to align the outgoing SP for compiled code. __ movptr(rdi, rsp);
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -610,14 +610,6 @@ const BasicType *sig_bt, const VMRegPair *regs) { - // - // We will only enter here from an interpreted frame and never from after - // passing thru a c2i. Azul allowed this but we do not. If we lose the - // race and use a c2i we will remain interpreted for the race loser(s). - // This removes all sorts of headaches on the x86 side and also eliminates - // the possibility of having c2i -> i2c -> c2i -> ... endless transitions. - - // Note: r13 contains the senderSP on entry. We must preserve it since // we may do a i2c -> c2i transition if we lose a race where compiled // code goes non-entrant while we get args ready. @@ -627,6 +619,7 @@ // save code can segv when fxsave instructions find improperly // aligned stack pointer. + // Pick up the return address __ movptr(rax, Address(rsp, 0)); // Must preserve original SP for loading incoming arguments because
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -240,9 +240,30 @@ BLOCK_COMMENT("call_stub_return_address:"); return_address = __ pc(); - Label common_return; +#ifdef COMPILER2 + { + Label L_skip; + if (UseSSE >= 2) { + __ verify_FPU(0, "call_stub_return"); + } else { + for (int i = 1; i < 8; i++) { + __ ffree(i); + } - __ BIND(common_return); + // UseSSE <= 1 so double result should be left on TOS + __ movl(rsi, result_type); + __ cmpl(rsi, T_DOUBLE); + __ jcc(Assembler::equal, L_skip); + if (UseSSE == 0) { + // UseSSE == 0 so float result should be left on TOS + __ cmpl(rsi, T_FLOAT); + __ jcc(Assembler::equal, L_skip); + } + __ ffree(0); + } + __ BIND(L_skip); + } +#endif // COMPILER2 // store result depending on type // (everything that is not T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT) @@ -305,37 +326,6 @@ } __ jmp(exit); - // If we call compiled code directly from the call stub we will - // need to adjust the return back to the call stub to a specialized - // piece of code that can handle compiled results and cleaning the fpu - // stack. compiled code will be set to return here instead of the - // return above that handles interpreter returns. - - BLOCK_COMMENT("call_stub_compiled_return:"); - StubRoutines::x86::set_call_stub_compiled_return( __ pc()); - -#ifdef COMPILER2 - if (UseSSE >= 2) { - __ verify_FPU(0, "call_stub_compiled_return"); - } else { - for (int i = 1; i < 8; i++) { - __ ffree(i); - } - - // UseSSE <= 1 so double result should be left on TOS - __ movl(rsi, result_type); - __ cmpl(rsi, T_DOUBLE); - __ jcc(Assembler::equal, common_return); - if (UseSSE == 0) { - // UseSSE == 0 so float result should be left on TOS - __ cmpl(rsi, T_FLOAT); - __ jcc(Assembler::equal, common_return); - } - __ ffree(0); - } -#endif /* COMPILER2 */ - __ jmp(common_return); - return start; }
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,5 @@ // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. -address StubRoutines::x86::_verify_mxcsr_entry = NULL; -address StubRoutines::x86::_verify_fpu_cntrl_wrd_entry= NULL; -address StubRoutines::x86::_call_stub_compiled_return = NULL; +address StubRoutines::x86::_verify_mxcsr_entry = NULL; +address StubRoutines::x86::_verify_fpu_cntrl_wrd_entry = NULL;
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,24 +44,14 @@ friend class VMStructs; private: - // If we call compiled code directly from the call stub we will - // need to adjust the return back to the call stub to a specialized - // piece of code that can handle compiled results and cleaning the fpu - // stack. The variable holds that location. - static address _call_stub_compiled_return; static address _verify_mxcsr_entry; static address _verify_fpu_cntrl_wrd_entry; - static jint _mxcsr_std; public: static address verify_mxcsr_entry() { return _verify_mxcsr_entry; } static address verify_fpu_cntrl_wrd_entry() { return _verify_fpu_cntrl_wrd_entry; } - - static address get_call_stub_compiled_return() { return _call_stub_compiled_return; } - static void set_call_stub_compiled_return(address ret) { _call_stub_compiled_return = ret; } }; - static bool returns_to_call_stub(address return_pc) { return (return_pc == _call_stub_return_address) || - return_pc == x86::get_call_stub_compiled_return(); } + static bool returns_to_call_stub(address return_pc) { return return_pc == _call_stub_return_address; } #endif // CPU_X86_VM_STUBROUTINES_X86_32_HPP
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -177,9 +177,7 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { TosState incoming_state = state; - - Label interpreter_entry; - address compiled_entry = __ pc(); + address entry = __ pc(); #ifdef COMPILER2 // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases @@ -197,14 +195,6 @@ __ MacroAssembler::verify_FPU(0, "generate_return_entry_for compiled"); } - __ jmp(interpreter_entry, relocInfo::none); - // emit a sentinel we can test for when converting an interpreter - // entry point to a compiled entry point. - __ a_long(Interpreter::return_sentinel); - __ a_long((int)compiled_entry); - address entry = __ pc(); - __ bind(interpreter_entry); - // In SSE mode, interpreter returns FP results in xmm0 but they need // to end up back on the FPU so it can operate on them. if (incoming_state == ftos && UseSSE >= 1) {
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -190,13 +190,7 @@ } -address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, - int step) { - - // amd64 doesn't need to do anything special about compiled returns - // to the interpreter so the code that exists on x86 to place a sentinel - // here and the specialized cleanup code is not needed here. - +address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { address entry = __ pc(); // Restore stack bottom in case i2c adjusted stack
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1710,39 +1710,6 @@ __ pop(rdi); // get return address __ mov(rsp, rdx); // set sp to sender sp - - Label skip; - Label chkint; - - // The interpreter frame we have removed may be returning to - // either the callstub or the interpreter. Since we will - // now be returning from a compiled (OSR) nmethod we must - // adjust the return to the return were it can handler compiled - // results and clean the fpu stack. This is very similar to - // what a i2c adapter must do. - - // Are we returning to the call stub? - - __ cmp32(rdi, ExternalAddress(StubRoutines::_call_stub_return_address)); - __ jcc(Assembler::notEqual, chkint); - - // yes adjust to the specialized call stub return. - assert(StubRoutines::x86::get_call_stub_compiled_return() != NULL, "must be set"); - __ lea(rdi, ExternalAddress(StubRoutines::x86::get_call_stub_compiled_return())); - __ jmp(skip); - - __ bind(chkint); - - // Are we returning to the interpreter? Look for sentinel - - __ cmpl(Address(rdi, -2*wordSize), Interpreter::return_sentinel); - __ jcc(Assembler::notEqual, skip); - - // Adjust to compiled return back to interpreter - - __ movptr(rdi, Address(rdi, -wordSize)); - __ bind(skip); - // Align stack pointer for compiled code (note that caller is // responsible for undoing this fixup by remembering the old SP // in an rbp,-relative location)
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/x86_32.ad Sun Mar 06 20:32:49 2011 -0800 @@ -12629,16 +12629,16 @@ ins_pipe( pipe_slow ); %} -instruct string_compare(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eBXRegI cnt2, - eAXRegI result, regXD tmp1, regXD tmp2, eFlagsReg cr) %{ +instruct string_compare(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2, + eAXRegI result, regXD tmp1, eFlagsReg cr) %{ match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); - - format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %} + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} ins_encode %{ __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, $result$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister); + $tmp1$$XMMRegister); %} ins_pipe( pipe_slow ); %}
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/x86/vm/x86_64.ad Sun Mar 06 20:32:49 2011 -0800 @@ -11583,17 +11583,17 @@ ins_pipe(pipe_slow); %} -instruct string_compare(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rbx_RegI cnt2, - rax_RegI result, regD tmp1, regD tmp2, rFlagsReg cr) +instruct string_compare(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, + rax_RegI result, regD tmp1, rFlagsReg cr) %{ match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); - - format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %} + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + + format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %} ins_encode %{ __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, $result$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister); + $tmp1$$XMMRegister); %} ins_pipe( pipe_slow ); %}
--- a/hotspot/src/cpu/zero/vm/stubRoutines_zero.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/zero/vm/stubRoutines_zero.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright 2008, 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,7 +30,3 @@ #ifdef TARGET_OS_FAMILY_linux # include "thread_linux.inline.hpp" #endif - -#ifdef IA32 -address StubRoutines::x86::_call_stub_compiled_return = NULL; -#endif // IA32
--- a/hotspot/src/cpu/zero/vm/stubRoutines_zero.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/cpu/zero/vm/stubRoutines_zero.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -48,13 +48,4 @@ method_handles_adapters_code_size = 0 }; -#ifdef IA32 - class x86 { - friend class VMStructs; - - private: - static address _call_stub_compiled_return; - }; -#endif // IA32 - #endif // CPU_ZERO_VM_STUBROUTINES_ZERO_HPP
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1975,7 +1975,11 @@ #ifndef RTLD_DL_SYMENT #define RTLD_DL_SYMENT 1 #endif - Sym * info; +#ifdef _LP64 + Elf64_Sym * info; +#else + Elf32_Sym * info; +#endif if (dladdr1_func((void *)addr, &dlinfo, (void **)&info, RTLD_DL_SYMENT)) { if ((char *)dlinfo.dli_saddr + info->st_size > (char *)addr) { @@ -6424,4 +6428,3 @@ INTERRUPTIBLE_RETURN_INT_NORESTART(::bind(fd, him, len),\ os::Solaris::clear_interrupted); } -
--- a/hotspot/src/os/windows/vm/perfMemory_windows.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -298,8 +298,8 @@ static char* get_user_name_slow(int vmid) { // directory search - char* oldest_user = NULL; - time_t oldest_ctime = 0; + char* latest_user = NULL; + time_t latest_ctime = 0; const char* tmpdirname = os::get_temp_directory(); @@ -375,18 +375,29 @@ continue; } - // compare and save filename with latest creation time - if (statbuf.st_size > 0 && statbuf.st_ctime > oldest_ctime) { - - if (statbuf.st_ctime > oldest_ctime) { - char* user = strchr(dentry->d_name, '_') + 1; + // If we found a matching file with a newer creation time, then + // save the user name. The newer creation time indicates that + // we found a newer incarnation of the process associated with + // vmid. Due to the way that Windows recycles pids and the fact + // that we can't delete the file from the file system namespace + // until last close, it is possible for there to be more than + // one hsperfdata file with a name matching vmid (diff users). + // + // We no longer ignore hsperfdata files where (st_size == 0). + // In this function, all we're trying to do is determine the + // name of the user that owns the process associated with vmid + // so the size doesn't matter. Very rarely, we have observed + // hsperfdata files where (st_size == 0) and the st_size field + // later becomes the expected value. + // + if (statbuf.st_ctime > latest_ctime) { + char* user = strchr(dentry->d_name, '_') + 1; - if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user); - oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1); + if (latest_user != NULL) FREE_C_HEAP_ARRAY(char, latest_user); + latest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1); - strcpy(oldest_user, user); - oldest_ctime = statbuf.st_ctime; - } + strcpy(latest_user, user); + latest_ctime = statbuf.st_ctime; } FREE_C_HEAP_ARRAY(char, filename); @@ -399,7 +410,7 @@ os::closedir(tmpdirp); FREE_C_HEAP_ARRAY(char, tdbuf); - return(oldest_user); + return(latest_user); } // return the name of the user that owns the process identified by vmid. @@ -1339,6 +1350,38 @@ CloseHandle(fh); fh = NULL; return NULL; + } else { + // We created the file mapping, but rarely the size of the + // backing store file is reported as zero (0) which can cause + // failures when trying to use the hsperfdata file. + struct stat statbuf; + int ret_code = ::stat(filename, &statbuf); + if (ret_code == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("Could not get status information from file %s: %s\n", + filename, strerror(errno)); + } + CloseHandle(fmh); + CloseHandle(fh); + fh = NULL; + fmh = NULL; + return NULL; + } + + // We could always call FlushFileBuffers() but the Microsoft + // docs indicate that it is considered expensive so we only + // call it when we observe the size as zero (0). + if (statbuf.st_size == 0 && FlushFileBuffers(fh) != TRUE) { + DWORD lasterror = GetLastError(); + if (PrintMiscellaneous && Verbose) { + warning("could not flush file %s: %d\n", filename, lasterror); + } + CloseHandle(fmh); + CloseHandle(fh); + fh = NULL; + fmh = NULL; + return NULL; + } } // the file has been successfully created and the file mapping
--- a/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007, 2008, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -300,4 +300,18 @@ (intptr_t) compare_value); } +inline jlong Atomic::load(volatile jlong* src) { + volatile jlong dest; + os::atomic_copy64(src, &dest); + return dest; +} + +inline void Atomic::store(jlong store_value, jlong* dest) { + os::atomic_copy64((volatile jlong*)&store_value, (volatile jlong*)dest); +} + +inline void Atomic::store(jlong store_value, volatile jlong* dest) { + os::atomic_copy64((volatile jlong*)&store_value, dest); +} + #endif // OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_INLINE_HPP
--- a/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -67,7 +67,6 @@ inline void Atomic_move_long(volatile jlong* src, volatile jlong* dst) { #ifdef COMPILER2 // Compiler2 does not support v8, it is used only for v9. - assert (VM_Version::v9_instructions_work(), "only supported on v9"); _Atomic_move_long_v9(src, dst); #else // The branch is cheaper then emulated LDD.
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -189,14 +189,22 @@ tty->print_cr("cpu_info.implementation: %s", implementation); } #endif - if (strncmp(implementation, "SPARC64", 7) == 0) { + // Convert to UPPER case before compare. + char* impl = strdup(implementation); + + for (int i = 0; impl[i] != 0; i++) + impl[i] = (char)toupper((uint)impl[i]); + if (strstr(impl, "SPARC64") != NULL) { features |= sparc64_family_m; - } else if (strncmp(implementation, "UltraSPARC-T", 12) == 0) { + } else if (strstr(impl, "SPARC-T") != NULL) { features |= T_family_m; - if (strncmp(implementation, "UltraSPARC-T1", 13) == 0) { + if (strstr(impl, "SPARC-T1") != NULL) { features |= T1_model_m; } + } else { + assert(strstr(impl, "SPARC") != NULL, "should be sparc"); } + free((void*)impl); break; } } // for(
--- a/hotspot/src/os_cpu/windows_x86/vm/unwind_windows_x86.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/os_cpu/windows_x86/vm/unwind_windows_x86.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ PVOID HandlerData; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; -#if MSC_VER < 1500 +#if _MSC_VER < 1500 /* Not needed for VS2008 compiler, comes from winnt.h. */ typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE) (
--- a/hotspot/src/share/tools/ProjectCreator/BuildConfig.java Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/tools/ProjectCreator/BuildConfig.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,12 +51,14 @@ if (vars == null) vars = new Hashtable(); String flavourBuild = flavour + "_" + build; + String platformName = getFieldString(null, "PlatformName"); System.out.println(); System.out.println(flavourBuild); - put("Name", getCI().makeCfgName(flavourBuild)); + put("Name", getCI().makeCfgName(flavourBuild, platformName)); put("Flavour", flavour); put("Build", build); + put("PlatformName", platformName); // ones mentioned above were needed to expand format String buildBase = expandFormat(getFieldString(null, "BuildBase")); @@ -93,7 +95,7 @@ protected void initDefaultLinkerFlags() { Vector linkerFlags = new Vector(); - linkerFlags.addAll(getCI().getBaseLinkerFlags( get("OutputDir"), get("OutputDll"))); + linkerFlags.addAll(getCI().getBaseLinkerFlags( get("OutputDir"), get("OutputDll"), get("PlatformName"))); put("LinkerFlags", linkerFlags); } @@ -115,18 +117,15 @@ } - Vector getPreferredPaths(MacroDefinitions macros) { + Vector getPreferredPaths() { Vector preferredPaths = new Vector(); + // In the case of multiple files with the same name in - // different subdirectories, prefer the versions specified in - // the platform file as the "os_family" and "arch" macros. - for (Iterator iter = macros.getMacros(); iter.hasNext(); ) { - Macro macro = (Macro) iter.next(); - if (macro.name.equals("os_family") || - macro.name.equals("arch")) { - preferredPaths.add(macro.contents); - } - } + // different subdirectories, prefer these versions + preferredPaths.add("windows"); + preferredPaths.add("x86"); + preferredPaths.add("closed"); + // Also prefer "opto" over "adlc" for adlcVMDeps.hpp preferredPaths.add("opto"); @@ -137,18 +136,7 @@ void handleDB() { WinGammaPlatform platform = (WinGammaPlatform)getField(null, "PlatformObject"); - File incls = new File(get("OutputDir")+Util.sep+"incls"); - - incls.mkdirs(); - - MacroDefinitions macros = new MacroDefinitions(); - try { - macros.readFrom(getFieldString(null, "Platform"), false); - } catch (Exception e) { - throw new RuntimeException(e); - } - - putSpecificField("AllFilesHash", computeAllFiles(platform, macros)); + putSpecificField("AllFilesHash", computeAllFiles(platform)); } @@ -190,10 +178,10 @@ ht.put(expandFormat(key), expandFormat(value)); } - Hashtable computeAllFiles(WinGammaPlatform platform, MacroDefinitions macros) { + Hashtable computeAllFiles(WinGammaPlatform platform) { Hashtable rv = new Hashtable(); DirectoryTree tree = getSourceTree(get("SourceBase"), getFieldString(null, "StartAt")); - Vector preferredPaths = getPreferredPaths(macros); + Vector preferredPaths = getPreferredPaths(); // Hold errors until end Vector filesNotFound = new Vector(); @@ -228,8 +216,7 @@ System.err.println("Error: some files were not found or " + "appeared in multiple subdirectories of " + "directory " + get("SourceBase") + " and could not " + - "be resolved with the os_family and arch " + - "macros in the platform file."); + "be resolved with os_family and arch."); if (filesNotFound.size() != 0) { System.err.println("Files not found:"); for (Iterator iter = filesNotFound.iterator(); @@ -254,10 +241,14 @@ Vector sysDefines = new Vector(); sysDefines.add("WIN32"); sysDefines.add("_WINDOWS"); - sysDefines.add("HOTSPOT_BUILD_USER="+System.getProperty("user.name")); + sysDefines.add("HOTSPOT_BUILD_USER=\\\""+System.getProperty("user.name")+"\\\""); sysDefines.add("HOTSPOT_BUILD_TARGET=\\\""+get("Build")+"\\\""); sysDefines.add("_JNI_IMPLEMENTATION_"); - sysDefines.add("HOTSPOT_LIB_ARCH=\\\"i386\\\""); + if (vars.get("PlatformName").equals("Win32")) { + sysDefines.add("HOTSPOT_LIB_ARCH=\\\"i386\\\""); + } else { + sysDefines.add("HOTSPOT_LIB_ARCH=\\\"amd64\\\""); + } sysDefines.addAll(defines); @@ -710,7 +701,7 @@ } abstract class CompilerInterface { abstract Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir); - abstract Vector getBaseLinkerFlags(String outDir, String outDll); + abstract Vector getBaseLinkerFlags(String outDir, String outDll, String platformName); abstract Vector getDebugCompilerFlags(String opt); abstract Vector getDebugLinkerFlags(); abstract void getAdditionalNonKernelLinkerFlags(Vector rv); @@ -718,7 +709,7 @@ abstract Vector getProductLinkerFlags(); abstract String getOptFlag(); abstract String getNoOptFlag(); - abstract String makeCfgName(String flavourBuild); + abstract String makeCfgName(String flavourBuild, String platformName); void addAttr(Vector receiver, String attr, String value) { receiver.add(attr); receiver.add(value);
--- a/hotspot/src/share/tools/ProjectCreator/DirectoryTree.java Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/tools/ProjectCreator/DirectoryTree.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,6 +55,9 @@ private Vector nodes = new Vector(); public FileIterator(Node rootNode) { + if(rootNode == null) { + return; + } nodes.add(rootNode); prune(); } @@ -112,10 +115,7 @@ throws IllegalArgumentException { File root = new File(Util.normalize(baseDirectory)); if (!root.isDirectory()) { - throw new IllegalArgumentException("baseDirectory \"" + - baseDirectory + - "\" does not exist or " + - "is not a directory"); + return; } try { root = root.getCanonicalFile();
--- a/hotspot/src/share/tools/ProjectCreator/FileFormatException.java Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/tools/ProjectCreator/FileFormatException.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,9 @@ * */ +@SuppressWarnings("serial") public class FileFormatException extends Exception { + public FileFormatException() { super(); }
--- a/hotspot/src/share/tools/ProjectCreator/Macro.java Tue Mar 01 15:24:46 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * 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 - * 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. - * - */ - -public class Macro { - public String name; - public String contents; -}
--- a/hotspot/src/share/tools/ProjectCreator/MacroDefinitions.java Tue Mar 01 15:24:46 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -import java.io.*; -import java.util.*; - -public class MacroDefinitions { - private Vector macros; - - public MacroDefinitions() { - macros = new Vector(); - } - - public void addMacro(String name, String contents) { - Macro macro = new Macro(); - macro.name = name; - macro.contents = contents; - macros.add(macro); - } - - private boolean lineIsEmpty(String s) { - for (int i = 0; i < s.length(); i++) { - if (!Character.isWhitespace(s.charAt(i))) { - return false; - } - } - return true; - } - - public void readFrom(String fileName, boolean missingOk) - throws FileNotFoundException, FileFormatException, IOException { - BufferedReader reader = null; - try { - reader = new BufferedReader(new FileReader(fileName)); - } catch (FileNotFoundException e) { - if (missingOk) { - return; - } else { - throw(e); - } - } - String line; - do { - line = reader.readLine(); - if (line != null) { - // This had to be rewritten (compare to Database.java) - // because the Solaris platform file has been - // repurposed and now contains "macros" with spaces in - // them. - - if ((!line.startsWith("//")) && - (!lineIsEmpty(line))) { - int nameBegin = -1; - int nameEnd = -1; - boolean gotEquals = false; - int contentsBegin = -1; - int contentsEnd = -1; - - int i = 0; - // Scan forward for beginning of name - while (i < line.length()) { - if (!Character.isWhitespace(line.charAt(i))) { - break; - } - i++; - } - nameBegin = i; - - // Scan forward for end of name - while (i < line.length()) { - if (Character.isWhitespace(line.charAt(i))) { - break; - } - i++; - } - nameEnd = i; - - // Scan forward for equals sign - while (i < line.length()) { - if (line.charAt(i) == '=') { - gotEquals = true; - break; - } - i++; - } - - // Scan forward for start of contents - i++; - while (i < line.length()) { - if (!Character.isWhitespace(line.charAt(i))) { - break; - } - i++; - } - contentsBegin = i; - - // Scan *backward* for end of contents - i = line.length() - 1; - while (i >= 0) { - if (!Character.isWhitespace(line.charAt(i))) { - break; - } - } - contentsEnd = i+1; - - // Now do consistency check - if (!((nameBegin < nameEnd) && - (nameEnd < contentsBegin) && - (contentsBegin < contentsEnd) && - (gotEquals == true))) { - throw new FileFormatException( - "Expected \"macroname = value\", " + - "but found: " + line - ); - } - - String name = line.substring(nameBegin, nameEnd); - String contents = line.substring(contentsBegin, - contentsEnd); - addMacro(name, contents); - } - } - } while (line != null); - reader.close(); - } - - /** This returns an Iterator of Macros. You should not mutate the - returned Macro objects or use the Iterator to remove - macros. */ - public Iterator getMacros() { - return macros.iterator(); - } -}
--- a/hotspot/src/share/tools/ProjectCreator/Util.java Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/tools/ProjectCreator/Util.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ return sb.toString(); } - static String join(String padder, String v[]) { + static String join(String padder, String v[]) { StringBuffer sb = new StringBuffer(); for (int i=0; i<v.length; i++) { @@ -80,9 +80,16 @@ static String normalize(String file) { - return file.replace('\\', '/'); + file = file.replace('\\', '/'); + if (file.length() > 2) { + if (file.charAt(1) == ':' && file.charAt(2) == '/') { + // convert drive letter to uppercase + String drive = file.substring(0, 1).toUpperCase(); + return drive + file.substring(1); + } + } + return file; } static String sep = File.separator; - static String os = "Win32"; //System.getProperty("os.name"); }
--- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatform.java Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatform.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -235,13 +235,6 @@ (locationsInTree.size() == 0)) { filesNotFound.add(fileName); } else if (locationsInTree.size() > 1) { - // We shouldn't have duplicate file names in our workspace. - System.err.println(); - System.err.println("There are multiple files named as: " + fileName); - System.exit(-1); - // The following code could be safely removed if we don't need duplicate - // file names. - // Iterate through them, trying to find one with a // preferred path search: @@ -336,7 +329,7 @@ String projectName = getProjectName(projectFileName, ext); - writeProjectFile(projectFileName, projectName, createAllConfigs()); + writeProjectFile(projectFileName, projectName, createAllConfigs(BuildConfig.getFieldString(null, "PlatformName"))); } protected void writePrologue(String[] args) { @@ -376,7 +369,13 @@ HsArgHandler.STRING ), - new HsArgRule("-projectFileName", + new HsArgRule("-platformName", + "PlatformName", + null, + HsArgHandler.STRING + ), + + new HsArgRule("-projectFileName", "ProjectFileName", null, HsArgHandler.STRING @@ -394,12 +393,6 @@ HsArgHandler.STRING ), - new HsArgRule("-platform", - "Platform", - null, - HsArgHandler.STRING - ), - new HsArgRule("-absoluteInclude", "AbsoluteInclude", null, @@ -590,28 +583,27 @@ BuildConfig.putField(null, "PlatformObject", this); } - Vector createAllConfigs() { + Vector createAllConfigs(String platform) { Vector allConfigs = new Vector(); allConfigs.add(new C1DebugConfig()); - boolean b = true; - if (b) { - allConfigs.add(new C1FastDebugConfig()); - allConfigs.add(new C1ProductConfig()); + allConfigs.add(new C1FastDebugConfig()); + allConfigs.add(new C1ProductConfig()); - allConfigs.add(new C2DebugConfig()); - allConfigs.add(new C2FastDebugConfig()); - allConfigs.add(new C2ProductConfig()); + allConfigs.add(new C2DebugConfig()); + allConfigs.add(new C2FastDebugConfig()); + allConfigs.add(new C2ProductConfig()); - allConfigs.add(new TieredDebugConfig()); - allConfigs.add(new TieredFastDebugConfig()); - allConfigs.add(new TieredProductConfig()); + allConfigs.add(new TieredDebugConfig()); + allConfigs.add(new TieredFastDebugConfig()); + allConfigs.add(new TieredProductConfig()); - allConfigs.add(new CoreDebugConfig()); - allConfigs.add(new CoreFastDebugConfig()); - allConfigs.add(new CoreProductConfig()); + allConfigs.add(new CoreDebugConfig()); + allConfigs.add(new CoreFastDebugConfig()); + allConfigs.add(new CoreProductConfig()); + if (platform.equals("Win32")) { allConfigs.add(new KernelDebugConfig()); allConfigs.add(new KernelFastDebugConfig()); allConfigs.add(new KernelProductConfig());
--- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC6.java Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC6.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -223,7 +223,7 @@ return rv; } - Vector getBaseLinkerFlags(String outDir, String outDll) { + Vector getBaseLinkerFlags(String outDir, String outDll, String platformName) { Vector rv = new Vector(); rv.add("PROP Ignore_Export_Lib 0"); @@ -231,8 +231,12 @@ rv.add("ADD CPP /MD"); rv.add("ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib " + " advapi32.lib shell32.lib ole32.lib oleaut32.lib winmm.lib"); + String machine = "/machine:I386"; + if (platformName.equals("x64")) { + machine = "/machine:X64"; + } rv.add("ADD LINK32 /out:\""+outDll+"\" "+ - " /nologo /subsystem:windows /machine:I386" + + " /nologo /subsystem:windows /machine:" + machine + " /nologo /base:\"0x8000000\" /subsystem:windows /dll" + " /export:JNI_GetDefaultJavaVMInitArgs /export:JNI_CreateJavaVM /export:JNI_GetCreatedJavaVMs "+ " /export:jio_snprintf /export:jio_printf /export:jio_fprintf /export:jio_vfprintf "+ @@ -287,7 +291,7 @@ return "d"; } - String makeCfgName(String flavourBuild) { - return "vm - "+ Util.os + " " + flavourBuild; + String makeCfgName(String flavourBuild, String platform) { + return "vm - "+ platform + " " + flavourBuild; } }
--- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC7.java Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC7.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ public void writeProjectFile(String projectFileName, String projectName, Vector allConfigs) throws IOException { System.out.println(); - System.out.println(" Writing .vcproj file..."); + System.out.println(" Writing .vcproj file: "+projectFileName); // If we got this far without an error, we're safe to actually // write the .vcproj file printWriter = new PrintWriter(new FileWriter(projectFileName)); @@ -54,9 +54,8 @@ "SccLocalPath", "" } ); - startTag("Platforms", null); - tag("Platform", new String[] {"Name", Util.os}); + tag("Platform", new String[] {"Name", (String) BuildConfig.getField(null, "PlatformName")}); endTag("Platforms"); startTag("Configurations", null); @@ -81,12 +80,47 @@ abstract class NameFilter { - protected String fname; + protected String fname; abstract boolean match(FileInfo fi); String filterString() { return ""; } String name() { return this.fname;} + + @Override + // eclipse auto-generated + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + getOuterType().hashCode(); + result = prime * result + ((fname == null) ? 0 : fname.hashCode()); + return result; + } + + @Override + // eclipse auto-generated + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NameFilter other = (NameFilter) obj; + if (!getOuterType().equals(other.getOuterType())) + return false; + if (fname == null) { + if (other.fname != null) + return false; + } else if (!fname.equals(other.fname)) + return false; + return true; + } + + // eclipse auto-generated + private WinGammaPlatformVC7 getOuterType() { + return WinGammaPlatformVC7.this; + } } class DirectoryFilter extends NameFilter { @@ -109,9 +143,50 @@ boolean match(FileInfo fi) { - int lastSlashIndex = fi.full.lastIndexOf('/'); - String fullDir = fi.full.substring(0, lastSlashIndex); - return fullDir.endsWith(dir); + int lastSlashIndex = fi.full.lastIndexOf('/'); + String fullDir = fi.full.substring(0, lastSlashIndex); + return fullDir.endsWith(dir); + } + + @Override + // eclipse auto-generated + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + getOuterType().hashCode(); + result = prime * result + baseLen; + result = prime * result + ((dir == null) ? 0 : dir.hashCode()); + result = prime * result + dirLen; + return result; + } + + @Override + // eclipse auto-generated + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + DirectoryFilter other = (DirectoryFilter) obj; + if (!getOuterType().equals(other.getOuterType())) + return false; + if (baseLen != other.baseLen) + return false; + if (dir == null) { + if (other.dir != null) + return false; + } else if (!dir.equals(other.dir)) + return false; + if (dirLen != other.dirLen) + return false; + return true; + } + + // eclipse auto-generated + private WinGammaPlatformVC7 getOuterType() { + return WinGammaPlatformVC7.this; } } @@ -232,32 +307,39 @@ DirectoryFilter container = null; for(FileInfo fileInfo : files) { - if (!fileInfo.full.startsWith(sbase)) { - continue; - } + if (!fileInfo.full.startsWith(sbase)) { + continue; + } + + int lastSlash = fileInfo.full.lastIndexOf('/'); + String dir = fileInfo.full.substring(sbase.length(), lastSlash); + if(dir.equals("share/vm")) { + // skip files directly in share/vm - should only be precompiled.hpp which is handled below + continue; + } + if (!dir.equals(currentDir)) { + currentDir = dir; + if (container != null && !rv.contains(container)) { + rv.add(container); + } - int lastSlash = fileInfo.full.lastIndexOf('/'); - String dir = fileInfo.full.substring(sbase.length(), lastSlash); - if(dir.equals("share/vm")) { - // skip files directly in share/vm - should only be precompiled.hpp which is handled below - continue; - } - if (!dir.equals(currentDir)) { - currentDir = dir; - if (container != null) { - rv.add(container); - } - - // remove "share/vm/" from names - String name = dir; - if (dir.startsWith("share/vm/")) { - name = dir.substring("share/vm/".length(), dir.length()); - } - container = new DirectoryFilter(name, dir, sbase); - } + // remove "share/vm/" from names + String name = dir; + if (dir.startsWith("share/vm/")) { + name = dir.substring("share/vm/".length(), dir.length()); + } + DirectoryFilter newfilter = new DirectoryFilter(name, dir, sbase); + int i = rv.indexOf(newfilter); + if(i == -1) { + container = newfilter; + } else { + // if the filter already exists, reuse it + container = (DirectoryFilter) rv.get(i); + } + } } - if (container != null) { - rv.add(container); + if (container != null && !rv.contains(container)) { + rv.add(container); } ContainerFilter generated = new ContainerFilter("Generated"); @@ -583,7 +665,7 @@ return rv; } - Vector getBaseLinkerFlags(String outDir, String outDll) { + Vector getBaseLinkerFlags(String outDir, String outDll, String platformName) { Vector rv = new Vector(); addAttr(rv, "Name", "VCLinkerTool"); @@ -610,8 +692,13 @@ addAttr(rv, "SubSystem", "2"); addAttr(rv, "BaseAddress", "0x8000000"); addAttr(rv, "ImportLibrary", outDir+Util.sep+"jvm.lib"); - // Set /MACHINE option. 1 is machineX86 - addAttr(rv, "TargetMachine", "1"); + if(platformName.equals("Win32")) { + // Set /MACHINE option. 1 is X86 + addAttr(rv, "TargetMachine", "1"); + } else { + // Set /MACHINE option. 17 is X64 + addAttr(rv, "TargetMachine", "17"); + } return rv; } @@ -656,12 +743,6 @@ addAttr(rv, "Optimization", "2"); // Set /Oy- option addAttr(rv, "OmitFramePointers", "FALSE"); - } - - Vector getProductCompilerFlags() { - Vector rv = new Vector(); - - getProductCompilerFlags_common(rv); // Set /Ob option. 1 is expandOnlyInline addAttr(rv, "InlineFunctionExpansion", "1"); // Set /GF option. @@ -670,6 +751,12 @@ addAttr(rv, "RuntimeLibrary", "2"); // Set /Gy option addAttr(rv, "EnableFunctionLevelLinking", "TRUE"); + } + + Vector getProductCompilerFlags() { + Vector rv = new Vector(); + + getProductCompilerFlags_common(rv); return rv; } @@ -693,7 +780,7 @@ return "0"; } - String makeCfgName(String flavourBuild) { - return flavourBuild + "|" + Util.os; + String makeCfgName(String flavourBuild, String platform) { + return flavourBuild + "|" + platform; } }
--- a/hotspot/src/share/vm/adlc/adlc.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/adlc/adlc.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,11 +42,6 @@ using namespace std; #endif -// make sure the MSC_VER and _MSC_VER settings make sense -#if _MSC_VER != MSC_VER && (_MSC_VER != 1400 || MSC_VER != 1399) -#error "Something is wrong with the detection of MSC_VER in the makefiles" -#endif - #if _MSC_VER >= 1400 #define strdup _strdup #endif
--- a/hotspot/src/share/vm/adlc/output_c.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/adlc/output_c.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1698,7 +1698,75 @@ fprintf(fp,"\n"); } // done generating expand rule - else if( node->_matrule != NULL ) { + // Generate projections for instruction's additional DEFs and KILLs + if( ! node->expands() && (node->needs_projections() || node->has_temps())) { + // Get string representing the MachNode that projections point at + const char *machNode = "this"; + // Generate the projections + fprintf(fp," // Add projection edges for additional defs or kills\n"); + + // Examine each component to see if it is a DEF or KILL + node->_components.reset(); + // Skip the first component, if already handled as (SET dst (...)) + Component *comp = NULL; + // For kills, the choice of projection numbers is arbitrary + int proj_no = 1; + bool declared_def = false; + bool declared_kill = false; + + while( (comp = node->_components.iter()) != NULL ) { + // Lookup register class associated with operand type + Form *form = (Form*)_globalNames[comp->_type]; + assert( form, "component type must be a defined form"); + OperandForm *op = form->is_operand(); + + if (comp->is(Component::TEMP)) { + fprintf(fp, " // TEMP %s\n", comp->_name); + if (!declared_def) { + // Define the variable "def" to hold new MachProjNodes + fprintf(fp, " MachTempNode *def;\n"); + declared_def = true; + } + if (op && op->_interface && op->_interface->is_RegInterface()) { + fprintf(fp," def = new (C) MachTempNode(state->MachOperGenerator( %s, C ));\n", + machOperEnum(op->_ident)); + fprintf(fp," add_req(def);\n"); + // The operand for TEMP is already constructed during + // this mach node construction, see buildMachNode(). + // + // int idx = node->operand_position_format(comp->_name); + // fprintf(fp," set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n", + // idx, machOperEnum(op->_ident)); + } else { + assert(false, "can't have temps which aren't registers"); + } + } else if (comp->isa(Component::KILL)) { + fprintf(fp, " // DEF/KILL %s\n", comp->_name); + + if (!declared_kill) { + // Define the variable "kill" to hold new MachProjNodes + fprintf(fp, " MachProjNode *kill;\n"); + declared_kill = true; + } + + assert( op, "Support additional KILLS for base operands"); + const char *regmask = reg_mask(*op); + const char *ideal_type = op->ideal_type(_globalNames, _register); + + if (!op->is_bound_register()) { + syntax_err(node->_linenum, "In %s only bound registers can be killed: %s %s\n", + node->_ident, comp->_type, comp->_name); + } + + fprintf(fp," kill = "); + fprintf(fp,"new (C, 1) MachProjNode( %s, %d, (%s), Op_%s );\n", + machNode, proj_no++, regmask, ideal_type); + fprintf(fp," proj_list.push(kill);\n"); + } + } + } + + if( !node->expands() && node->_matrule != NULL ) { // Remove duplicated operands and inputs which use the same name. // Seach through match operands for the same name usage. uint cur_num_opnds = node->num_opnds(); @@ -1752,72 +1820,6 @@ } } - - // Generate projections for instruction's additional DEFs and KILLs - if( ! node->expands() && (node->needs_projections() || node->has_temps())) { - // Get string representing the MachNode that projections point at - const char *machNode = "this"; - // Generate the projections - fprintf(fp," // Add projection edges for additional defs or kills\n"); - - // Examine each component to see if it is a DEF or KILL - node->_components.reset(); - // Skip the first component, if already handled as (SET dst (...)) - Component *comp = NULL; - // For kills, the choice of projection numbers is arbitrary - int proj_no = 1; - bool declared_def = false; - bool declared_kill = false; - - while( (comp = node->_components.iter()) != NULL ) { - // Lookup register class associated with operand type - Form *form = (Form*)_globalNames[comp->_type]; - assert( form, "component type must be a defined form"); - OperandForm *op = form->is_operand(); - - if (comp->is(Component::TEMP)) { - fprintf(fp, " // TEMP %s\n", comp->_name); - if (!declared_def) { - // Define the variable "def" to hold new MachProjNodes - fprintf(fp, " MachTempNode *def;\n"); - declared_def = true; - } - if (op && op->_interface && op->_interface->is_RegInterface()) { - fprintf(fp," def = new (C) MachTempNode(state->MachOperGenerator( %s, C ));\n", - machOperEnum(op->_ident)); - fprintf(fp," add_req(def);\n"); - int idx = node->operand_position_format(comp->_name); - fprintf(fp," set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n", - idx, machOperEnum(op->_ident)); - } else { - assert(false, "can't have temps which aren't registers"); - } - } else if (comp->isa(Component::KILL)) { - fprintf(fp, " // DEF/KILL %s\n", comp->_name); - - if (!declared_kill) { - // Define the variable "kill" to hold new MachProjNodes - fprintf(fp, " MachProjNode *kill;\n"); - declared_kill = true; - } - - assert( op, "Support additional KILLS for base operands"); - const char *regmask = reg_mask(*op); - const char *ideal_type = op->ideal_type(_globalNames, _register); - - if (!op->is_bound_register()) { - syntax_err(node->_linenum, "In %s only bound registers can be killed: %s %s\n", - node->_ident, comp->_type, comp->_name); - } - - fprintf(fp," kill = "); - fprintf(fp,"new (C, 1) MachProjNode( %s, %d, (%s), Op_%s );\n", - machNode, proj_no++, regmask, ideal_type); - fprintf(fp," proj_list.push(kill);\n"); - } - } - } - // If the node is a MachConstantNode, insert the MachConstantBaseNode edge. // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input). if (node->is_mach_constant()) { @@ -3776,12 +3778,10 @@ } dont_care = true; // For each operand not in the match rule, call MachOperGenerator - // with the enum for the opcode that needs to be built - // and the node just built, the parent of the operand. + // with the enum for the opcode that needs to be built. ComponentList clist = inst->_components; int index = clist.operand_position(comp->_name, comp->_usedef); const char *opcode = machOperEnum(comp->_type); - const char *parent = "node"; fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index); fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode); }
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -491,10 +491,11 @@ // to start profiling on its own. _method->ensure_method_data(); } - } else if (is_profiling() && _would_profile) { + } else if (is_profiling()) { ciMethodData *md = method->method_data_or_null(); - assert(md != NULL, "Sanity"); - md->set_would_profile(_would_profile); + if (md != NULL) { + md->set_would_profile(_would_profile); + } } }
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -412,13 +412,17 @@ fail_type = _unloaded_ciinstance_klass; } KlassHandle found_klass; - if (!require_local) { - klassOop kls = SystemDictionary::find_constrained_instance_or_array_klass( - sym, loader, KILL_COMPILE_ON_FATAL_(fail_type)); - found_klass = KlassHandle(THREAD, kls); - } else { - klassOop kls = SystemDictionary::find_instance_or_array_klass( - sym, loader, domain, KILL_COMPILE_ON_FATAL_(fail_type)); + { + ttyUnlocker ttyul; // release tty lock to avoid ordering problems + MutexLocker ml(Compile_lock); + klassOop kls; + if (!require_local) { + kls = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, + KILL_COMPILE_ON_FATAL_(fail_type)); + } else { + kls = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, + KILL_COMPILE_ON_FATAL_(fail_type)); + } found_klass = KlassHandle(THREAD, kls); }
--- a/hotspot/src/share/vm/ci/ciField.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/ci/ciField.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -212,9 +212,9 @@ // may change. The three examples are java.lang.System.in, // java.lang.System.out, and java.lang.System.err. - klassOop k = _holder->get_klassOop(); + Handle k = _holder->get_klassOop(); assert( SystemDictionary::System_klass() != NULL, "Check once per vm"); - if( k == SystemDictionary::System_klass() ) { + if( k() == SystemDictionary::System_klass() ) { // Check offsets for case 2: System.in, System.out, or System.err if( _offset == java_lang_System::in_offset_in_bytes() || _offset == java_lang_System::out_offset_in_bytes() ||
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -46,6 +46,7 @@ ciKlass(h_k), _non_static_fields(NULL) { assert(get_Klass()->oop_is_instance(), "wrong type"); + assert(get_instanceKlass()->is_loaded(), "must be at least loaded"); instanceKlass* ik = get_instanceKlass(); AccessFlags access_flags = ik->access_flags();
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -331,7 +331,7 @@ length, CHECK_(nullHandle)); constantPoolOop constant_pool = oopFactory::new_constantPool(length, - methodOopDesc::IsSafeConc, + oopDesc::IsSafeConc, CHECK_(nullHandle)); constantPoolHandle cp (THREAD, constant_pool); @@ -1929,10 +1929,9 @@ } // All sizing information for a methodOop is finally available, now create it - methodOop m_oop = oopFactory::new_method( - code_length, access_flags, linenumber_table_length, - total_lvt_length, checked_exceptions_length, - methodOopDesc::IsSafeConc, CHECK_(nullHandle)); + methodOop m_oop = oopFactory::new_method(code_length, access_flags, linenumber_table_length, + total_lvt_length, checked_exceptions_length, + oopDesc::IsSafeConc, CHECK_(nullHandle)); methodHandle m (THREAD, m_oop); ClassLoadingService::add_class_method_size(m_oop->size()*HeapWordSize);
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/classfile/classLoader.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1290,6 +1290,15 @@ int ClassLoader::_compile_the_world_counter = 0; static int _codecache_sweep_counter = 0; +// Filter out all exceptions except OOMs +static void clear_pending_exception_if_not_oom(TRAPS) { + if (HAS_PENDING_EXCEPTION && + !PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) { + CLEAR_PENDING_EXCEPTION; + } + // The CHECK at the caller will propagate the exception out +} + void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { int len = (int)strlen(name); if (len > 6 && strcmp(".class", name + len - 6) == 0) { @@ -1312,12 +1321,12 @@ k->initialize(THREAD); } bool exception_occurred = HAS_PENDING_EXCEPTION; - CLEAR_PENDING_EXCEPTION; + clear_pending_exception_if_not_oom(CHECK); if (CompileTheWorldPreloadClasses && k.not_null()) { constantPoolKlass::preload_and_initialize_all_classes(k->constants(), THREAD); if (HAS_PENDING_EXCEPTION) { // If something went wrong in preloading we just ignore it - CLEAR_PENDING_EXCEPTION; + clear_pending_exception_if_not_oom(CHECK); tty->print_cr("Preloading failed for (%d) %s", _compile_the_world_counter, buffer); } } @@ -1344,7 +1353,7 @@ CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_initial_compile, methodHandle(), 0, "CTW", THREAD); if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; + clear_pending_exception_if_not_oom(CHECK); tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string()); } if (TieredCompilation) { @@ -1358,7 +1367,7 @@ CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_full_optimization, methodHandle(), 0, "CTW", THREAD); if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; + clear_pending_exception_if_not_oom(CHECK); tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string()); } }
--- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -322,8 +322,14 @@ klassOop LoaderConstraintTable::find_constrained_klass(Symbol* name, Handle loader) { LoaderConstraintEntry *p = *(find_loader_constraint(name, loader)); - if (p != NULL && p->klass() != NULL) + if (p != NULL && p->klass() != NULL) { + if (Klass::cast(p->klass())->oop_is_instance() && !instanceKlass::cast(p->klass())->is_loaded()) { + // Only return fully loaded classes. Classes found through the + // constraints might still be in the process of loading. + return NULL; + } return p->klass(); + } // No constraints, or else no klass loaded yet. return NULL;
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1690,6 +1690,8 @@ void SystemDictionary::add_to_hierarchy(instanceKlassHandle k, TRAPS) { assert(k.not_null(), "just checking"); + assert_locked_or_safepoint(Compile_lock); + // Link into hierachy. Make sure the vtables are initialized before linking into k->append_to_sibling_list(); // add to superklass/sibling list k->process_interfaces(THREAD); // handle all "implements" declarations @@ -2152,6 +2154,9 @@ } +// Try to find a class name using the loader constraints. The +// loader constraints might know about a class that isn't fully loaded +// yet and these will be ignored. klassOop SystemDictionary::find_constrained_instance_or_array_klass( Symbol* class_name, Handle class_loader, TRAPS) {
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -768,7 +768,9 @@ // Initialize the compilation queue void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) { EXCEPTION_MARK; +#ifndef ZERO assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?"); +#endif // !ZERO if (c2_compiler_count > 0) { _c2_method_queue = new CompileQueue("C2MethodQueue", MethodCompileQueue_lock); }
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1040,9 +1040,10 @@ } else { // must read from what 'p' points to in each loop. klassOop k = ((volatile oopDesc*)p)->klass_or_null(); - if (k != NULL && - ((oopDesc*)p)->is_parsable() && - ((oopDesc*)p)->is_conc_safe()) { + // We trust the size of any object that has a non-NULL + // klass and (for those in the perm gen) is parsable + // -- irrespective of its conc_safe-ty. + if (k != NULL && ((oopDesc*)p)->is_parsable()) { assert(k->is_oop(), "Should really be klass oop."); oop o = (oop)p; assert(o->is_oop(), "Should be an oop"); @@ -1051,6 +1052,7 @@ assert(res != 0, "Block size should not be 0"); return res; } else { + // May return 0 if P-bits not present. return c->block_size_if_printezis_bits(p); } }
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -6360,18 +6360,16 @@ // A variant of the above (block_size_using_printezis_bits()) except // that we return 0 if the P-bits are not yet set. size_t CMSCollector::block_size_if_printezis_bits(HeapWord* addr) const { - if (_markBitMap.isMarked(addr)) { - assert(_markBitMap.isMarked(addr + 1), "Missing Printezis bit?"); + if (_markBitMap.isMarked(addr + 1)) { + assert(_markBitMap.isMarked(addr), "P-bit can be set only for marked objects"); HeapWord* nextOneAddr = _markBitMap.getNextMarkedWordAddress(addr + 2); size_t size = pointer_delta(nextOneAddr + 1, addr); assert(size == CompactibleFreeListSpace::adjustObjectSize(size), "alignment problem"); assert(size >= 3, "Necessary for Printezis marks to work"); return size; - } else { - assert(!_markBitMap.isMarked(addr + 1), "Bit map inconsistency?"); - return 0; - } + } + return 0; } HeapWord* CMSCollector::next_card_start_after_block(HeapWord* addr) const { @@ -9212,7 +9210,6 @@ size_t MarkDeadObjectsClosure::do_blk(HeapWord* addr) { size_t res = _sp->block_size_no_stall(addr, _collector); - assert(res != 0, "Should always be able to compute a size"); if (_sp->block_is_obj(addr)) { if (_live_bit_map->isMarked(addr)) { // It can't have been dead in a previous cycle @@ -9221,6 +9218,7 @@ _dead_bit_map->mark(addr); // mark the dead object } } + // Could be 0, if the block size could not be computed without stalling. return res; }
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -132,8 +132,7 @@ VM_GenCollectFullConcurrent(unsigned int gc_count_before, unsigned int full_gc_count_before, GCCause::Cause gc_cause) - : VM_GC_Operation(gc_count_before, full_gc_count_before, true /* full */) { - _gc_cause = gc_cause; + : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */) { assert(FullGCCount_lock != NULL, "Error"); assert(UseAsyncConcMarkSweepGC, "Else will hang caller"); }
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ public: VM_G1OperationWithAllocRequest(unsigned int gc_count_before, size_t word_size) - : VM_GC_Operation(gc_count_before), + : VM_GC_Operation(gc_count_before, GCCause::_allocation_failure), _word_size(word_size), _result(NULL), _pause_succeeded(false) { } HeapWord* result() { return _result; } bool pause_succeeded() { return _pause_succeeded; } @@ -55,9 +55,7 @@ VM_G1CollectFull(unsigned int gc_count_before, unsigned int full_gc_count_before, GCCause::Cause cause) - : VM_GC_Operation(gc_count_before, full_gc_count_before) { - _gc_cause = cause; - } + : VM_GC_Operation(gc_count_before, cause, full_gc_count_before) { } virtual VMOp_Type type() const { return VMOp_G1CollectFull; } virtual void doit(); virtual const char* name() const {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,9 +112,12 @@ yg_cur_size = MAX2(yg_cur_size, yg_min_size); og_min_size = align_size_up(og_min_size, og_align); - og_max_size = align_size_up(og_max_size, og_align); + // Align old gen size down to preserve specified heap size. + assert(og_align == yg_align, "sanity"); + og_max_size = align_size_down(og_max_size, og_align); + og_max_size = MAX2(og_max_size, og_min_size); size_t og_cur_size = - align_size_up(_collector_policy->old_gen_size(), og_align); + align_size_down(_collector_policy->old_gen_size(), og_align); og_cur_size = MAX2(og_cur_size, og_min_size); pg_min_size = align_size_up(pg_min_size, pg_align);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1196,11 +1196,6 @@ static inline void adjust_pointer(oop* p) { adjust_pointer(p, false); } static inline void adjust_pointer(narrowOop* p) { adjust_pointer(p, false); } - template <class T> - static inline void adjust_pointer(T* p, - HeapWord* beg_addr, - HeapWord* end_addr); - // Reference Processing static ReferenceProcessor* const ref_processor() { return _ref_processor; } @@ -1408,15 +1403,6 @@ return ((HeapWord*) k) >= dense_prefix(perm_space_id); } -template <class T> -inline void PSParallelCompact::adjust_pointer(T* p, - HeapWord* beg_addr, - HeapWord* end_addr) { - if (is_in((HeapWord*)p, beg_addr, end_addr)) { - adjust_pointer(p); - } -} - #ifdef ASSERT inline void PSParallelCompact::check_new_location(HeapWord* old_addr, HeapWord* new_addr)
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ // The following methods are used by the parallel scavenge collector VM_ParallelGCFailedAllocation::VM_ParallelGCFailedAllocation(size_t size, bool is_tlab, unsigned int gc_count) : - VM_GC_Operation(gc_count), + VM_GC_Operation(gc_count, GCCause::_allocation_failure), _size(size), _is_tlab(is_tlab), _result(NULL) @@ -57,7 +57,7 @@ VM_ParallelGCFailedPermanentAllocation::VM_ParallelGCFailedPermanentAllocation(size_t size, unsigned int gc_count, unsigned int full_gc_count) : - VM_GC_Operation(gc_count, full_gc_count, true /* full */), + VM_GC_Operation(gc_count, GCCause::_allocation_failure, full_gc_count, true /* full */), _size(size), _result(NULL) { @@ -80,9 +80,8 @@ VM_ParallelGCSystemGC::VM_ParallelGCSystemGC(unsigned int gc_count, unsigned int full_gc_count, GCCause::Cause gc_cause) : - VM_GC_Operation(gc_count, full_gc_count, true /* full */) + VM_GC_Operation(gc_count, gc_cause, full_gc_count, true /* full */) { - _gc_cause = gc_cause; } void VM_ParallelGCSystemGC::doit() {
--- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,6 +87,8 @@ bool VM_GC_Operation::doit_prologue() { assert(Thread::current()->is_Java_thread(), "just checking"); + assert(((_gc_cause != GCCause::_no_gc) && + (_gc_cause != GCCause::_no_cause_specified)), "Illegal GCCause"); acquire_pending_list_lock(); // If the GC count has changed someone beat us to the collection
--- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,6 +85,7 @@ public: VM_GC_Operation(unsigned int gc_count_before, + GCCause::Cause _cause, unsigned int full_gc_count_before = 0, bool full = false) { _full = full; @@ -92,7 +93,7 @@ _gc_count_before = gc_count_before; // A subclass constructor will likely overwrite the following - _gc_cause = GCCause::_no_cause_specified; + _gc_cause = _cause; _gc_locked = false; @@ -136,6 +137,7 @@ VM_GC_HeapInspection(outputStream* out, bool request_full_gc, bool need_prologue) : VM_GC_Operation(0 /* total collections, dummy, ignored */, + GCCause::_heap_inspection /* GC Cause */, 0 /* total full collections, dummy, ignored */, request_full_gc) { _out = out; @@ -160,7 +162,7 @@ VM_GenCollectForAllocation(size_t size, bool tlab, unsigned int gc_count_before) - : VM_GC_Operation(gc_count_before), + : VM_GC_Operation(gc_count_before, GCCause::_allocation_failure), _size(size), _tlab(tlab) { _res = NULL; @@ -182,9 +184,8 @@ unsigned int full_gc_count_before, GCCause::Cause gc_cause, int max_level) - : VM_GC_Operation(gc_count_before, full_gc_count_before, true /* full */), - _max_level(max_level) - { _gc_cause = gc_cause; } + : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */), + _max_level(max_level) { } ~VM_GenCollectFull() {} virtual VMOp_Type type() const { return VMOp_GenCollectFull; } virtual void doit(); @@ -199,7 +200,7 @@ unsigned int gc_count_before, unsigned int full_gc_count_before, GCCause::Cause gc_cause) - : VM_GC_Operation(gc_count_before, full_gc_count_before, true), + : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true), _size(size) { _res = NULL; _gc_cause = gc_cause;
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -100,8 +100,7 @@ } } -void CollectedHeap::check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) - { +void CollectedHeap::check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) { if (CheckMemoryInitialization && ZapUnusedHeapArea) { for (size_t slot = 0; slot < size; slot += 1) { assert((*(intptr_t*) (addr + slot)) == ((intptr_t) badHeapWordVal),
--- a/hotspot/src/share/vm/gc_interface/gcCause.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_interface/gcCause.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,28 +92,3 @@ } ShouldNotReachHere(); } - -#ifndef PRODUCT - -bool GCCause::is_for_full_collection(GCCause::Cause cause) { - bool result; - - // There are more GCCause::Cause types than listed here. - // For brevity, we list only those that cause full collections. - switch (cause) { - case _allocation_failure: - case _tenured_generation_full: - case _permanent_generation_full: - case _cms_generation_full: - case _last_ditch_collection: - result = true; - break; - - default: - result = false; - break; - } - return result; -} - -#endif // PRODUCT
--- a/hotspot/src/share/vm/gc_interface/gcCause.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/gc_interface/gcCause.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,8 +85,6 @@ // Return a string describing the GCCause. static const char* to_string(GCCause::Cause cause); - // Return true if the GCCause is for a full collection. - static bool is_for_full_collection(GCCause::Cause cause) PRODUCT_RETURN0; }; #endif // SHARE_VM_GC_INTERFACE_GCCAUSE_HPP
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1942,7 +1942,7 @@ constantPoolOop constants = istate->method()->constants(); if (!constants->tag_at(index).is_unresolved_klass()) { // Make sure klass is initialized and doesn't have a finalizer - oop entry = (klassOop) *constants->obj_at_addr(index); + oop entry = constants->slot_at(index).get_oop(); assert(entry->is_klass(), "Should be resolved klass"); klassOop k_entry = (klassOop) entry; assert(k_entry->klass_part()->oop_is_instance(), "Should be instanceKlass"); @@ -2032,7 +2032,7 @@ if (METHOD->constants()->tag_at(index).is_unresolved_klass()) { CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception); } - klassOop klassOf = (klassOop) *(METHOD->constants()->obj_at_addr(index)); + klassOop klassOf = (klassOop) METHOD->constants()->slot_at(index).get_oop(); klassOop objKlassOop = STACK_OBJECT(-1)->klass(); //ebx // // Check for compatibilty. This check must not GC!! @@ -2067,7 +2067,7 @@ if (METHOD->constants()->tag_at(index).is_unresolved_klass()) { CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception); } - klassOop klassOf = (klassOop) *(METHOD->constants()->obj_at_addr(index)); + klassOop klassOf = (klassOop) METHOD->constants()->slot_at(index).get_oop(); klassOop objKlassOop = STACK_OBJECT(-1)->klass(); // // Check for compatibilty. This check must not GC!!
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -67,13 +67,11 @@ // Creates a constant pool cache given a CPC map -// This creates the constant pool cache initially in a state -// that is unsafe for concurrent GC processing but sets it to -// a safe mode before the constant pool cache is returned. void Rewriter::make_constant_pool_cache(TRAPS) { const int length = _cp_cache_map.length(); constantPoolCacheOop cache = - oopFactory::new_constantPoolCache(length, methodOopDesc::IsUnsafeConc, CHECK); + oopFactory::new_constantPoolCache(length, CHECK); + No_Safepoint_Verifier nsv; cache->initialize(_cp_cache_map); // Don't bother with the next pass if there is no JVM_CONSTANT_InvokeDynamic.
--- a/hotspot/src/share/vm/libadt/vectset.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/libadt/vectset.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -350,28 +350,11 @@ return (int)_xor; } -//------------------------------iterate---------------------------------------- -SetI_ *VectorSet::iterate(uint &elem) const -{ - VSetI_ *foo = (new(ResourceObj::C_HEAP) VSetI_(this)); - elem = foo->next(); - return foo; -} - //============================================================================= -//------------------------------VSetI_----------------------------------------- -// Initialize the innards of a VectorSet iterator -VSetI_::VSetI_( const VectorSet *vset ) : s(vset) -{ - i = (uint)-1L; - j = (uint)-1L; - mask = (unsigned)(1L<<31); -} - //------------------------------next------------------------------------------- // Find and return the next element of a vector set, or return garbage and -// make "VSetI_::test()" fail. -uint VSetI_::next(void) +// make "VectorSetI::test()" fail. +uint VectorSetI::next(void) { j++; // Next element in word mask = (mask & max_jint) << 1;// Next bit in word
--- a/hotspot/src/share/vm/libadt/vectset.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/libadt/vectset.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,6 +98,9 @@ uint Size(void) const; // Number of elements in the Set. void Sort(void); // Sort before iterating int hash() const; // Hash function + void Reset(void) { // Reset a set + memset( data, 0, size*sizeof(uint32) ); + } /* Removed for MCC BUG operator const VectorSet* (void) const { return this; } */ @@ -148,8 +151,7 @@ private: - friend class VSetI_; - SetI_ *iterate(uint&) const; + SetI_ *iterate(uint&) const { ShouldNotCallThis(); return NULL; } // Removed }; //------------------------------Iteration-------------------------------------- @@ -158,22 +160,26 @@ // or may not be iterated over; untouched elements will be affected once. // Usage: for( VectorSetI i(s); i.test(); i++ ) { body = i.elem; } -class VSetI_ : public SetI_ { +class VectorSetI : public StackObj { friend class VectorSet; - friend class VectorSetI; const VectorSet *s; uint i, j; uint32 mask; - VSetI_(const VectorSet *vset); uint next(void); + +public: + uint elem; // The publically accessible element + + VectorSetI( const VectorSet *vset ) : + s(vset), + i((uint)-1L), + j((uint)-1L), + mask((unsigned)(1L<<31)) { + elem = next(); + } + + void operator ++(void) { elem = next(); } int test(void) { return i < s->size; } }; -class VectorSetI : public SetI { -public: - VectorSetI( const VectorSet *s ) : SetI(s) { } - void operator ++(void) { elem = ((VSetI_*)impl)->next(); } - int test(void) { return ((VSetI_*)impl)->test(); } -}; - #endif // SHARE_VM_LIBADT_VECTSET_HPP
--- a/hotspot/src/share/vm/memory/allocation.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/memory/allocation.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -157,7 +157,7 @@ void trace_heap_malloc(size_t size, const char* name, void* p) { // A lock is not needed here - tty uses a lock internally - tty->print_cr("Heap malloc " INTPTR_FORMAT " %7d %s", p, size, name == NULL ? "" : name); + tty->print_cr("Heap malloc " INTPTR_FORMAT " " SIZE_FORMAT " %s", p, size, name == NULL ? "" : name); } @@ -573,22 +573,27 @@ st->print("AllocatedObj(" INTPTR_FORMAT ")", this); } -size_t Arena::_bytes_allocated = 0; +julong Arena::_bytes_allocated = 0; + +void Arena::inc_bytes_allocated(size_t x) { inc_stat_counter(&_bytes_allocated, x); } AllocStats::AllocStats() { - start_mallocs = os::num_mallocs; - start_frees = os::num_frees; + start_mallocs = os::num_mallocs; + start_frees = os::num_frees; start_malloc_bytes = os::alloc_bytes; - start_res_bytes = Arena::_bytes_allocated; + start_mfree_bytes = os::free_bytes; + start_res_bytes = Arena::_bytes_allocated; } -int AllocStats::num_mallocs() { return os::num_mallocs - start_mallocs; } -size_t AllocStats::alloc_bytes() { return os::alloc_bytes - start_malloc_bytes; } -size_t AllocStats::resource_bytes() { return Arena::_bytes_allocated - start_res_bytes; } -int AllocStats::num_frees() { return os::num_frees - start_frees; } +julong AllocStats::num_mallocs() { return os::num_mallocs - start_mallocs; } +julong AllocStats::alloc_bytes() { return os::alloc_bytes - start_malloc_bytes; } +julong AllocStats::num_frees() { return os::num_frees - start_frees; } +julong AllocStats::free_bytes() { return os::free_bytes - start_mfree_bytes; } +julong AllocStats::resource_bytes() { return Arena::_bytes_allocated - start_res_bytes; } void AllocStats::print() { - tty->print("%d mallocs (%ldK), %d frees, %ldK resrc", - num_mallocs(), alloc_bytes()/K, num_frees(), resource_bytes()/K); + tty->print_cr(UINT64_FORMAT " mallocs (" UINT64_FORMAT "MB), " + UINT64_FORMAT" frees (" UINT64_FORMAT "MB), " UINT64_FORMAT "MB resrc", + num_mallocs(), alloc_bytes()/M, num_frees(), free_bytes()/M, resource_bytes()/M); }
--- a/hotspot/src/share/vm/memory/allocation.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/memory/allocation.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -202,10 +202,11 @@ char *_hwm, *_max; // High water mark and max in current chunk void* grow(size_t x); // Get a new Chunk of at least size x NOT_PRODUCT(size_t _size_in_bytes;) // Size of arena (used for memory usage tracing) - NOT_PRODUCT(static size_t _bytes_allocated;) // total #bytes allocated since start + NOT_PRODUCT(static julong _bytes_allocated;) // total #bytes allocated since start friend class AllocStats; debug_only(void* malloc(size_t size);) debug_only(void* internal_malloc_4(size_t x);) + NOT_PRODUCT(void inc_bytes_allocated(size_t x);) public: Arena(); Arena(size_t init_size); @@ -219,7 +220,7 @@ assert(is_power_of_2(ARENA_AMALLOC_ALIGNMENT) , "should be a power of 2"); x = ARENA_ALIGN(x); debug_only(if (UseMallocOnly) return malloc(x);) - NOT_PRODUCT(_bytes_allocated += x); + NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { return grow(x); } else { @@ -232,7 +233,7 @@ void *Amalloc_4(size_t x) { assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); debug_only(if (UseMallocOnly) return malloc(x);) - NOT_PRODUCT(_bytes_allocated += x); + NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { return grow(x); } else { @@ -252,7 +253,7 @@ size_t delta = (((size_t)_hwm + DALIGN_M1) & ~DALIGN_M1) - (size_t)_hwm; x += delta; #endif - NOT_PRODUCT(_bytes_allocated += x); + NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { return grow(x); // grow() returns a result aligned >= 8 bytes. } else { @@ -406,15 +407,16 @@ // for statistics #ifndef PRODUCT class AllocStats : StackObj { - int start_mallocs, start_frees; - size_t start_malloc_bytes, start_res_bytes; + julong start_mallocs, start_frees; + julong start_malloc_bytes, start_mfree_bytes, start_res_bytes; public: AllocStats(); - int num_mallocs(); // since creation of receiver - size_t alloc_bytes(); - size_t resource_bytes(); - int num_frees(); + julong num_mallocs(); // since creation of receiver + julong alloc_bytes(); + julong num_frees(); + julong free_bytes(); + julong resource_bytes(); void print(); }; #endif
--- a/hotspot/src/share/vm/memory/allocation.inline.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/memory/allocation.inline.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,20 @@ void trace_heap_malloc(size_t size, const char* name, void *p); void trace_heap_free(void *p); +#ifndef PRODUCT +// Increments unsigned long value for statistics (not atomic on MP). +inline void inc_stat_counter(volatile julong* dest, julong add_value) { +#if defined(SPARC) || defined(X86) + // Sparc and X86 have atomic jlong (8 bytes) instructions + julong value = Atomic::load((volatile jlong*)dest); + value += add_value; + Atomic::store((jlong)value, (volatile jlong*)dest); +#else + // possible word-tearing during load/store + *dest += add_value; +#endif +} +#endif // allocate using malloc; will fail if no memory available inline char* AllocateHeap(size_t size, const char* name = NULL) {
--- a/hotspot/src/share/vm/memory/oopFactory.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/memory/oopFactory.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -111,10 +111,9 @@ constantPoolCacheOop oopFactory::new_constantPoolCache(int length, - bool is_conc_safe, TRAPS) { constantPoolCacheKlass* ck = constantPoolCacheKlass::cast(Universe::constantPoolCacheKlassObj()); - return ck->allocate(length, is_conc_safe, CHECK_NULL); + return ck->allocate(length, CHECK_NULL); }
--- a/hotspot/src/share/vm/memory/oopFactory.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/memory/oopFactory.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -69,7 +69,6 @@ bool is_conc_safe, TRAPS); static constantPoolCacheOop new_constantPoolCache(int length, - bool is_conc_safe, TRAPS); // Instance classes
--- a/hotspot/src/share/vm/oops/arrayKlassKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/arrayKlassKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,27 +128,6 @@ } return klassKlass::oop_update_pointers(cm, obj); } - -int -arrayKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - assert(obj->is_klass(), "must be klass"); - arrayKlass* ak = arrayKlass::cast(klassOop(obj)); - - oop* p; - p = ak->adr_component_mirror(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - p = ak->adr_lower_dimension(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - p = ak->adr_higher_dimension(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - - { - HandleMark hm; - ak->vtable()->oop_update_pointers(cm, beg_addr, end_addr); - } - return klassKlass::oop_update_pointers(cm, obj, beg_addr, end_addr); -} #endif // SERIALGC // Printing
--- a/hotspot/src/share/vm/oops/compiledICHolderKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/compiledICHolderKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,21 +145,6 @@ PSParallelCompact::adjust_pointer(c->adr_holder_klass()); return c->object_size(); } - -int compiledICHolderKlass::oop_update_pointers(ParCompactionManager* cm, - oop obj, - HeapWord* beg_addr, - HeapWord* end_addr) { - assert(obj->is_compiledICHolder(), "must be compiledICHolder"); - compiledICHolderOop c = compiledICHolderOop(obj); - - oop* p; - p = c->adr_holder_method(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - p = c->adr_holder_klass(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - return c->object_size(); -} #endif // SERIALGC // Printing
--- a/hotspot/src/share/vm/oops/constMethodKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/constMethodKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -184,21 +184,6 @@ } return cm_oop->object_size(); } - -int constMethodKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, - HeapWord* end_addr) { - assert(obj->is_constMethod(), "should be constMethod"); - constMethodOop cm_oop = constMethodOop(obj); - - oop* const beg_oop = MAX2((oop*)beg_addr, cm_oop->oop_block_beg()); - oop* const end_oop = MIN2((oop*)end_addr, cm_oop->oop_block_end()); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { - PSParallelCompact::adjust_pointer(cur_oop); - } - - return cm_oop->object_size(); -} #endif // SERIALGC // Printing
--- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,26 +55,35 @@ constantPoolOop constantPoolKlass::allocate(int length, bool is_conc_safe, TRAPS) { int size = constantPoolOopDesc::object_size(length); KlassHandle klass (THREAD, as_klassOop()); - constantPoolOop c = - (constantPoolOop)CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); + assert(klass()->is_oop(), "Can't be null, else handlizing of c below won't work"); + constantPoolHandle pool; + { + constantPoolOop c = + (constantPoolOop)CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); + assert(c->klass_or_null() != NULL, "Handlizing below won't work"); + pool = constantPoolHandle(THREAD, c); + } - c->set_length(length); - c->set_tags(NULL); - c->set_cache(NULL); - c->set_operands(NULL); - c->set_pool_holder(NULL); - c->set_flags(0); + pool->set_length(length); + pool->set_tags(NULL); + pool->set_cache(NULL); + pool->set_operands(NULL); + pool->set_pool_holder(NULL); + pool->set_flags(0); // only set to non-zero if constant pool is merged by RedefineClasses - c->set_orig_length(0); + pool->set_orig_length(0); // if constant pool may change during RedefineClasses, it is created // unsafe for GC concurrent processing. - c->set_is_conc_safe(is_conc_safe); + pool->set_is_conc_safe(is_conc_safe); // all fields are initialized; needed for GC + // Note: because we may be in this "conc_unsafe" state when allocating + // t_oop below, which may in turn cause a GC, it is imperative that our + // size be correct, consistent and henceforth stable, at this stage. + assert(pool->is_oop() && pool->is_parsable(), "Else size() below is unreliable"); + assert(size == pool->size(), "size() is wrong"); + // initialize tag array - // Note: cannot introduce constant pool handle before since it is not - // completely initialized (no class) -> would cause assertion failure - constantPoolHandle pool (THREAD, c); typeArrayOop t_oop = oopFactory::new_permanent_byteArray(length, CHECK_NULL); typeArrayHandle tags (THREAD, t_oop); for (int index = 0; index < length; index++) { @@ -82,6 +91,8 @@ } pool->set_tags(tags()); + // Check that our size was stable at its old value. + assert(size == pool->size(), "size() changed"); return pool(); } @@ -271,40 +282,6 @@ return cp->object_size(); } -int -constantPoolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - assert (obj->is_constantPool(), "obj must be constant pool"); - constantPoolOop cp = (constantPoolOop) obj; - - // If the tags array is null we are in the middle of allocating this constant - // pool. - if (cp->tags() != NULL) { - oop* base = (oop*)cp->base(); - oop* const beg_oop = MAX2((oop*)beg_addr, base); - oop* const end_oop = MIN2((oop*)end_addr, base + cp->length()); - const size_t beg_idx = pointer_delta(beg_oop, base, sizeof(oop*)); - const size_t end_idx = pointer_delta(end_oop, base, sizeof(oop*)); - for (size_t cur_idx = beg_idx; cur_idx < end_idx; ++cur_idx, ++base) { - if (cp->is_pointer_entry(int(cur_idx))) { - PSParallelCompact::adjust_pointer(base); - } - } - } - - oop* p; - p = cp->tags_addr(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - p = cp->cache_addr(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - p = cp->operands_addr(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - p = cp->pool_holder_addr(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - - return cp->object_size(); -} - void constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { assert(obj->is_constantPool(), "should be constant pool"); constantPoolOop cp = (constantPoolOop) obj;
--- a/hotspot/src/share/vm/oops/cpCacheKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/cpCacheKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,43 +49,31 @@ constantPoolCacheOop constantPoolCacheKlass::allocate(int length, - bool is_conc_safe, TRAPS) { // allocate memory int size = constantPoolCacheOopDesc::object_size(length); KlassHandle klass (THREAD, as_klassOop()); - // This is the original code. The code from permanent_obj_allocate() - // was in-lined to allow the setting of is_conc_safe before the klass - // is installed. + // Commented out below is the original code. The code from + // permanent_obj_allocate() was in-lined so that we could + // set the _length field, necessary to correctly compute its + // size(), before setting its klass word further below. // constantPoolCacheOop cache = (constantPoolCacheOop) // CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); oop obj = CollectedHeap::permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL); - constantPoolCacheOop cache = (constantPoolCacheOop) obj; - cache->set_is_conc_safe(is_conc_safe); - // The store to is_conc_safe must be visible before the klass - // is set. This should be done safely because _is_conc_safe has - // been declared volatile. If there are any problems, consider adding - // OrderAccess::storestore(); - CollectedHeap::post_allocation_install_obj_klass(klass, obj, size); NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj, size)); - - // The length field affects the size of the object. The allocation - // above allocates the correct size (see calculation of "size") but - // the size() method of the constant pool cache oop will not reflect - // that size until the correct length is set. - cache->set_length(length); + constantPoolCacheOop cache = (constantPoolCacheOop) obj; + assert(!UseConcMarkSweepGC || obj->klass_or_null() == NULL, + "klass should be NULL here when using CMS"); + cache->set_length(length); // should become visible before klass is set below. + cache->set_constant_pool(NULL); - // The store of the length must be visible before is_conc_safe is - // set to a safe state. - // This should be done safely because _is_conc_safe has - // been declared volatile. If there are any problems, consider adding - // OrderAccess::storestore(); - cache->set_is_conc_safe(methodOopDesc::IsSafeConc); - cache->set_constant_pool(NULL); + OrderAccess::storestore(); + obj->set_klass(klass()); + assert(cache->size() == size, "Incorrect cache->size()"); return cache; } @@ -176,11 +164,6 @@ return size; } -bool constantPoolCacheKlass::oop_is_conc_safe(oop obj) const { - assert(obj->is_constantPoolCache(), "should be constant pool"); - return constantPoolCacheOop(obj)->is_conc_safe(); -} - #ifndef SERIALGC void constantPoolCacheKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { @@ -220,25 +203,6 @@ return cache->object_size(); } - -int -constantPoolCacheKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, - HeapWord* end_addr) { - assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); - constantPoolCacheOop cache = (constantPoolCacheOop)obj; - - // Iteration over constant pool cache instance variables - oop* p; - p = (oop*)cache->constant_pool_addr(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - - // Iteration over constant pool cache entries - for (int i = 0; i < cache->length(); ++i) { - cache->entry_at(i)->update_pointers(beg_addr, end_addr); - } - return cache->object_size(); -} #endif // SERIALGC void constantPoolCacheKlass::oop_print_on(oop obj, outputStream* st) {
--- a/hotspot/src/share/vm/oops/cpCacheKlass.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/cpCacheKlass.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -39,7 +39,7 @@ // Allocation DEFINE_ALLOCATE_PERMANENT(constantPoolCacheKlass); - constantPoolCacheOop allocate(int length, bool is_conc_safe, TRAPS); + constantPoolCacheOop allocate(int length, TRAPS); static klassOop create_klass(TRAPS); // Casting from klassOop @@ -55,7 +55,6 @@ // Garbage collection void oop_follow_contents(oop obj); int oop_adjust_pointers(oop obj); - virtual bool oop_is_conc_safe(oop obj) const; // Parallel Scavenge and Parallel Old PARALLEL_GC_DECLS
--- a/hotspot/src/share/vm/oops/cpCacheOop.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,15 +98,15 @@ // Atomically sets f1 if it is still NULL, otherwise it keeps the // current value. void ConstantPoolCacheEntry::set_f1_if_null_atomic(oop f1) { - // Use barriers as in oop_store - HeapWord* f1_addr = (HeapWord*) &_f1; - update_barrier_set_pre(f1_addr, f1); - void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL); - bool success = (result == NULL); - if (success) { - update_barrier_set((void*) f1_addr, f1); - } + // Use barriers as in oop_store + oop* f1_addr = (oop*) &_f1; + update_barrier_set_pre(f1_addr, f1); + void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL); + bool success = (result == NULL); + if (success) { + update_barrier_set(f1_addr, f1); } +} #ifdef ASSERT // It is possible to have two different dummy methodOops created @@ -368,16 +368,6 @@ PSParallelCompact::adjust_pointer((oop*)&_f2); } } - -void ConstantPoolCacheEntry::update_pointers(HeapWord* beg_addr, - HeapWord* end_addr) { - assert(in_words(size()) == 4, "check code below - may need adjustment"); - // field[1] is always oop or NULL - PSParallelCompact::adjust_pointer((oop*)&_f1, beg_addr, end_addr); - if (is_vfinal()) { - PSParallelCompact::adjust_pointer((oop*)&_f2, beg_addr, end_addr); - } -} #endif // SERIALGC // RedefineClasses() API support:
--- a/hotspot/src/share/vm/oops/cpCacheOop.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -287,7 +287,6 @@ #endif // SERIALGC void update_pointers(); - void update_pointers(HeapWord* beg_addr, HeapWord* end_addr); // RedefineClasses() API support: // If this constantPoolCacheEntry refers to old_method then update it @@ -321,9 +320,6 @@ private: int _length; constantPoolOop _constant_pool; // the corresponding constant pool - // If true, safe for concurrent GC processing, - // Set unconditionally in constantPoolCacheKlass::allocate() - volatile bool _is_conc_safe; // Sizing debug_only(friend class ClassVerifier;) @@ -390,12 +386,6 @@ return entry_at(primary_index); } - // GC support - // If the _length field has not been set, the size of the - // constantPoolCache cannot be correctly calculated. - bool is_conc_safe() { return _is_conc_safe; } - void set_is_conc_safe(bool v) { _is_conc_safe = v; } - // Code generation static ByteSize base_offset() { return in_ByteSize(sizeof(constantPoolCacheOopDesc)); } static ByteSize entry_offset(int raw_index) {
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1736,14 +1736,6 @@ PSParallelCompact::adjust_pointer(p), \ assert_nothing) } - -void instanceKlass::update_static_fields(HeapWord* beg_addr, HeapWord* end_addr) { - InstanceKlass_BOUNDED_OOP_ITERATE( \ - start_of_static_fields(), static_oop_field_size(), \ - beg_addr, end_addr, \ - PSParallelCompact::adjust_pointer(p), \ - assert_nothing ) -} #endif // SERIALGC void instanceKlass::oop_follow_contents(oop obj) { @@ -1876,15 +1868,6 @@ return size_helper(); } -int instanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - InstanceKlass_BOUNDED_OOP_MAP_ITERATE( \ - obj, beg_addr, end_addr, \ - PSParallelCompact::adjust_pointer(p), \ - assert_nothing) - return size_helper(); -} - void instanceKlass::push_static_fields(PSPromotionManager* pm) { InstanceKlass_OOP_ITERATE( \ start_of_static_fields(), static_oop_field_size(), \
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -740,7 +740,6 @@ void follow_static_fields(ParCompactionManager* cm); void copy_static_fields(ParCompactionManager* cm); void update_static_fields(); - void update_static_fields(HeapWord* beg_addr, HeapWord* end_addr); #endif // SERIALGC // Naming
--- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -353,35 +353,6 @@ return ik->object_size(); } -int instanceKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, - HeapWord* end_addr) { - assert(obj->is_klass(),"must be a klass"); - assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), - "must be instance klass"); - - instanceKlass* ik = instanceKlass::cast(klassOop(obj)); - ik->update_static_fields(beg_addr, end_addr); - ik->vtable()->oop_update_pointers(cm, beg_addr, end_addr); - ik->itable()->oop_update_pointers(cm, beg_addr, end_addr); - - oop* const beg_oop = MAX2((oop*)beg_addr, ik->oop_block_beg()); - oop* const end_oop = MIN2((oop*)end_addr, ik->oop_block_end()); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { - PSParallelCompact::adjust_pointer(cur_oop); - } - - // The oop_map_cache, jni_ids and jni_id_map are allocated from the C heap, - // and so don't lie within any 'Chunk' boundaries. Update them when the - // lowest addressed oop in the instanceKlass 'oop_block' is updated. - if (beg_oop == ik->oop_block_beg()) { - OopClosure* closure = PSParallelCompact::adjust_root_pointer_closure(); - iterate_c_heap_oops(ik, closure); - } - - klassKlass::oop_update_pointers(cm, obj, beg_addr, end_addr); - return ik->object_size(); -} #endif // SERIALGC klassOop
--- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -344,33 +344,6 @@ } return size_helper(); } - - -template <class T> void -specialized_oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - T* p; - T* referent_addr = p = (T*)java_lang_ref_Reference::referent_addr(obj); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - T* next_addr = p = (T*)java_lang_ref_Reference::next_addr(obj); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - T* discovered_addr = p = (T*)java_lang_ref_Reference::discovered_addr(obj); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - debug_only(trace_reference_gc("instanceRefKlass::oop_update_ptrs", obj, - referent_addr, next_addr, discovered_addr);) -} - -int -instanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - instanceKlass::oop_update_pointers(cm, obj, beg_addr, end_addr); - if (UseCompressedOops) { - specialized_oop_update_pointers<narrowOop>(cm, obj, beg_addr, end_addr); - } else { - specialized_oop_update_pointers<oop>(cm, obj, beg_addr, end_addr); - } - return size_helper(); -} #endif // SERIALGC void instanceRefKlass::update_nonstatic_oop_maps(klassOop k) {
--- a/hotspot/src/share/vm/oops/klassKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/klassKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,19 +188,6 @@ return oop_size(obj); } - -int klassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - Klass* k = Klass::cast(klassOop(obj)); - - oop* const beg_oop = MAX2((oop*)beg_addr, k->oop_block_beg()); - oop* const end_oop = MIN2((oop*)end_addr, k->oop_block_end()); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { - PSParallelCompact::adjust_pointer(cur_oop); - } - - return oop_size(obj); -} #endif // SERIALGC
--- a/hotspot/src/share/vm/oops/klassPS.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/klassPS.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,17 +37,13 @@ objects that do (or may) cross chunk boundaries; it updates only those \ oops that are in the region [beg_addr, end_addr). */ \ virtual void oop_follow_contents(ParCompactionManager* cm, oop obj); \ - virtual int oop_update_pointers(ParCompactionManager* cm, oop obj); \ - virtual int oop_update_pointers(ParCompactionManager* cm, oop obj, \ - HeapWord* beg_addr, HeapWord* end_addr); + virtual int oop_update_pointers(ParCompactionManager* cm, oop obj); // Pure virtual version for klass.hpp #define PARALLEL_GC_DECLS_PV \ virtual void oop_push_contents(PSPromotionManager* pm, oop obj) = 0; \ virtual void oop_follow_contents(ParCompactionManager* cm, oop obj) = 0; \ - virtual int oop_update_pointers(ParCompactionManager* cm, oop obj) = 0; \ - virtual int oop_update_pointers(ParCompactionManager* cm, oop obj, \ - HeapWord* beg_addr, HeapWord* end_addr) = 0; + virtual int oop_update_pointers(ParCompactionManager* cm, oop obj) = 0; #else // SERIALGC #define PARALLEL_GC_DECLS #define PARALLEL_GC_DECLS_PV
--- a/hotspot/src/share/vm/oops/klassVtable.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/klassVtable.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -677,25 +677,6 @@ PSParallelCompact::adjust_pointer(adr_method_at(i)); } } - -void klassVtable::oop_update_pointers(ParCompactionManager* cm, - HeapWord* beg_addr, HeapWord* end_addr) { - const int n = length(); - const int entry_size = vtableEntry::size(); - - int beg_idx = 0; - HeapWord* const method_0 = (HeapWord*)adr_method_at(0); - if (beg_addr > method_0) { - // it's safe to use cast, as we have guarantees on vtable size to be sane - beg_idx = int((pointer_delta(beg_addr, method_0) + entry_size - 1) / entry_size); - } - - oop* const beg_oop = adr_method_at(beg_idx); - oop* const end_oop = MIN2((oop*)end_addr, adr_method_at(n)); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; cur_oop += entry_size) { - PSParallelCompact::adjust_pointer(cur_oop); - } -} #endif // SERIALGC // Iterators @@ -820,25 +801,6 @@ ime++; } } - -void klassItable::oop_update_pointers(ParCompactionManager* cm, - HeapWord* beg_addr, HeapWord* end_addr) { - // offset table - itableOffsetEntry* ioe = offset_entry(0); - for(int i = 0; i < _size_offset_table; i++) { - oop* p = (oop*)&ioe->_interface; - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - ioe++; - } - - // method table - itableMethodEntry* ime = method_entry(0); - for(int j = 0; j < _size_method_table; j++) { - oop* p = (oop*)&ime->_method; - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - ime++; - } -} #endif // SERIALGC // Iterators
--- a/hotspot/src/share/vm/oops/klassVtable.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/klassVtable.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,8 +99,6 @@ // Parallel Old void oop_follow_contents(ParCompactionManager* cm); void oop_update_pointers(ParCompactionManager* cm); - void oop_update_pointers(ParCompactionManager* cm, - HeapWord* beg_addr, HeapWord* end_addr); #endif // SERIALGC // Iterators @@ -295,8 +293,6 @@ // Parallel Old void oop_follow_contents(ParCompactionManager* cm); void oop_update_pointers(ParCompactionManager* cm); - void oop_update_pointers(ParCompactionManager* cm, - HeapWord* beg_addr, HeapWord* end_addr); #endif // SERIALGC // Iterators
--- a/hotspot/src/share/vm/oops/methodDataKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/methodDataKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,25 +188,6 @@ } return m->object_size(); } - -int -methodDataKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - assert(obj->is_methodData(), "should be method data"); - - oop* p; - methodDataOop m = methodDataOop(obj); - - p = m->adr_method(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - - ResourceMark rm; - ProfileData* data; - for (data = m->first_data(); m->is_valid(data); data = m->next_data(data)) { - data->update_pointers(beg_addr, end_addr); - } - return m->object_size(); -} #endif // SERIALGC #ifndef PRODUCT
--- a/hotspot/src/share/vm/oops/methodDataOop.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/methodDataOop.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -271,17 +271,6 @@ } } } - -void ReceiverTypeData::update_pointers(HeapWord* beg_addr, HeapWord* end_addr) { - // The loop bounds could be computed based on beg_addr/end_addr and the - // boundary test hoisted outside the loop (see klassVTable for an example); - // however, row_limit() is small enough (2) to make that less efficient. - for (uint row = 0; row < row_limit(); row++) { - if (receiver_unchecked(row) != NULL) { - PSParallelCompact::adjust_pointer(adr_receiver(row), beg_addr, end_addr); - } - } -} #endif // SERIALGC #ifndef PRODUCT @@ -764,11 +753,13 @@ if (TieredCompilation) { _invocation_counter.init(); _backedge_counter.init(); + _invocation_counter_start = 0; + _backedge_counter_start = 0; _num_loops = 0; _num_blocks = 0; _highest_comp_level = 0; _highest_osr_comp_level = 0; - _would_profile = false; + _would_profile = true; } set_creation_mileage(mileage_of(method()));
--- a/hotspot/src/share/vm/oops/methodDataOop.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/methodDataOop.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -452,7 +452,6 @@ // Parallel old support virtual void follow_contents(ParCompactionManager* cm) {} virtual void update_pointers() {} - virtual void update_pointers(HeapWord* beg_addr, HeapWord* end_addr) {} #endif // SERIALGC // CI translation: ProfileData can represent both MethodDataOop data @@ -748,7 +747,6 @@ // Parallel old support virtual void follow_contents(ParCompactionManager* cm); virtual void update_pointers(); - virtual void update_pointers(HeapWord* beg_addr, HeapWord* end_addr); #endif // SERIALGC oop* adr_receiver(uint row) { @@ -1224,6 +1222,9 @@ InvocationCounter _invocation_counter; // Same for backedges. InvocationCounter _backedge_counter; + // Counter values at the time profiling started. + int _invocation_counter_start; + int _backedge_counter_start; // Number of loops and blocks is computed when compiling the first // time with C1. It is used to determine if method is trivial. short _num_loops; @@ -1333,6 +1334,28 @@ return backedge_counter()->count(); } + int invocation_count_start() { + if (invocation_counter()->carry()) { + return 0; + } + return _invocation_counter_start; + } + + int backedge_count_start() { + if (backedge_counter()->carry()) { + return 0; + } + return _backedge_counter_start; + } + + int invocation_count_delta() { return invocation_count() - invocation_count_start(); } + int backedge_count_delta() { return backedge_count() - backedge_count_start(); } + + void reset_start_counters() { + _invocation_counter_start = invocation_count(); + _backedge_counter_start = backedge_count(); + } + InvocationCounter* invocation_counter() { return &_invocation_counter; } InvocationCounter* backedge_counter() { return &_backedge_counter; }
--- a/hotspot/src/share/vm/oops/methodKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/methodKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -214,27 +214,6 @@ #endif // COMPILER2 return m->object_size(); } - -int methodKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - assert(obj->is_method(), "should be method"); - - oop* p; - methodOop m = methodOop(obj); - - p = m->adr_constMethod(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - p = m->adr_constants(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - -#ifdef COMPILER2 - if (m->method_data() != NULL) { - p = m->adr_method_data(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - } -#endif // COMPILER2 - return m->object_size(); -} #endif // SERIALGC #ifndef PRODUCT
--- a/hotspot/src/share/vm/oops/methodOop.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/methodOop.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -934,7 +934,7 @@ assert(m->signature() == signature, ""); assert(m->is_method_handle_invoke(), ""); #ifdef CC_INTERP - ResultTypeFinder rtf(signature()); + ResultTypeFinder rtf(signature); m->set_result_index(rtf.type()); #endif m->compute_size_of_parameters(THREAD); @@ -985,9 +985,11 @@ IsUnsafeConc, CHECK_(methodHandle())); methodHandle newm (THREAD, newm_oop); + NOT_PRODUCT(int nmsz = newm->is_parsable() ? newm->size() : -1;) int new_method_size = newm->method_size(); // Create a shallow copy of methodOopDesc part, but be careful to preserve the new constMethodOop constMethodOop newcm = newm->constMethod(); + NOT_PRODUCT(int ncmsz = newcm->is_parsable() ? newcm->size() : -1;) int new_const_method_size = newm->constMethod()->object_size(); memcpy(newm(), m(), sizeof(methodOopDesc)); @@ -999,9 +1001,19 @@ // or concurrent marking but those phases will be correct. Setting and // resetting is done in preference to a careful copying into newcm to // avoid having to know the precise layout of a constMethodOop. - m->constMethod()->set_is_conc_safe(false); + m->constMethod()->set_is_conc_safe(oopDesc::IsUnsafeConc); + assert(m->constMethod()->is_parsable(), "Should remain parsable"); + + // NOTE: this is a reachable object that transiently signals "conc_unsafe" + // However, no allocations are done during this window + // during which it is tagged conc_unsafe, so we are assured that any concurrent + // thread will not wait forever for the object to revert to "conc_safe". + // Further, any such conc_unsafe object will indicate a stable size + // through the transition. memcpy(newcm, m->constMethod(), sizeof(constMethodOopDesc)); - m->constMethod()->set_is_conc_safe(true); + m->constMethod()->set_is_conc_safe(oopDesc::IsSafeConc); + assert(m->constMethod()->is_parsable(), "Should remain parsable"); + // Reset correct method/const method, method size, and parameter info newcm->set_method(newm()); newm->set_constMethod(newcm); @@ -1035,6 +1047,8 @@ // Only set is_conc_safe to true when changes to newcm are // complete. + assert(!newm->is_parsable() || nmsz < 0 || newm->size() == nmsz, "newm->size() inconsistency"); + assert(!newcm->is_parsable() || ncmsz < 0 || newcm->size() == ncmsz, "newcm->size() inconsistency"); newcm->set_is_conc_safe(true); return newm; } @@ -1372,7 +1386,7 @@ } // See comment in methodOop.hpp which explains why this exists. -#if defined(_M_AMD64) && MSC_VER >= 1400 +#if defined(_M_AMD64) && _MSC_VER >= 1400 #pragma optimize("", off) void CompressedLineNumberWriteStream::write_pair(int bci, int line) { write_pair_inline(bci, line);
--- a/hotspot/src/share/vm/oops/methodOop.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/methodOop.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -144,9 +144,6 @@ public: - static const bool IsUnsafeConc = false; - static const bool IsSafeConc = true; - // accessors for instance variables constMethodOop constMethod() const { return _constMethod; } void set_constMethod(constMethodOop xconst) { oop_store_without_check((oop*)&_constMethod, (oop)xconst); } @@ -732,8 +729,8 @@ // Disabling optimization doesn't work for methods in header files // so we force it to call through the non-optimized version in the .cpp. // It's gross, but it's the only way we can ensure that all callers are -// fixed. MSC_VER is defined in build/windows/makefiles/compile.make. -#if defined(_M_AMD64) && MSC_VER >= 1400 +// fixed. _MSC_VER is defined by the windows compiler +#if defined(_M_AMD64) && _MSC_VER >= 1400 void write_pair(int bci, int line); #else void write_pair(int bci, int line) { write_pair_inline(bci, line); }
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -470,16 +470,6 @@ ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p)) return a->object_size(); } - -int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - assert (obj->is_objArray(), "obj must be obj array"); - objArrayOop a = objArrayOop(obj); - ObjArrayKlass_BOUNDED_OOP_ITERATE( \ - a, p, beg_addr, end_addr, \ - PSParallelCompact::adjust_pointer(p)) - return a->object_size(); -} #endif // SERIALGC // JVM support
--- a/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -254,22 +254,6 @@ return arrayKlassKlass::oop_update_pointers(cm, obj); } - -int objArrayKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, - HeapWord* end_addr) { - assert(obj->is_klass(), "must be klass"); - assert(klassOop(obj)->klass_part()->oop_is_objArray_slow(), "must be obj array"); - - oop* p; - objArrayKlass* oak = objArrayKlass::cast((klassOop)obj); - p = oak->element_klass_addr(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - p = oak->bottom_klass_addr(); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - - return arrayKlassKlass::oop_update_pointers(cm, obj, beg_addr, end_addr); -} #endif // SERIALGC #ifndef PRODUCT
--- a/hotspot/src/share/vm/oops/oop.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/oop.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,11 @@ static BarrierSet* _bs; public: + enum ConcSafeType { + IsUnsafeConc = false, + IsSafeConc = true + }; + markOop mark() const { return _mark; } markOop* mark_addr() const { return (markOop*) &_mark; } @@ -317,13 +322,6 @@ // Parallel Old void update_contents(ParCompactionManager* cm); - void update_contents(ParCompactionManager* cm, - HeapWord* begin_limit, - HeapWord* end_limit); - void update_contents(ParCompactionManager* cm, - klassOop old_klass, - HeapWord* begin_limit, - HeapWord* end_limit); void follow_contents(ParCompactionManager* cm); void follow_header(ParCompactionManager* cm); @@ -364,7 +362,6 @@ #ifndef SERIALGC // Parallel old void update_header(); - void update_header(HeapWord* beg_addr, HeapWord* end_addr); #endif // SERIALGC // mark-sweep support
--- a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,41 +57,6 @@ // Else skip it. The typeArrayKlass in the header never needs scavenging. } -inline void oopDesc::update_contents(ParCompactionManager* cm, - HeapWord* begin_limit, - HeapWord* end_limit) { - // The klass field must be updated before anything else - // can be done. - debug_only(klassOopDesc* original_klass = klass()); - - update_contents(cm, klass(), begin_limit, end_limit); -} - -inline void oopDesc::update_contents(ParCompactionManager* cm, - klassOop old_klass, - HeapWord* begin_limit, - HeapWord* end_limit) { - - klassOop updated_klass = - PSParallelCompact::summary_data().calc_new_klass(old_klass); - - // Needs to be boundary aware for the 64 bit case - // update_header(); - // The klass has moved. Is the location of the klass - // within the limits? - if ((((HeapWord*)&_metadata._klass) >= begin_limit) && - (((HeapWord*)&_metadata._klass) < end_limit)) { - set_klass(updated_klass); - } - - Klass* klass = updated_klass->klass_part(); - if (!klass->oop_is_typeArray()) { - // It might contain oops beyond the header, so take the virtual call. - klass->oop_update_pointers(cm, this, begin_limit, end_limit); - } - // Else skip it. The typeArrayKlass in the header never needs scavenging. -} - inline void oopDesc::follow_contents(ParCompactionManager* cm) { assert (PSParallelCompact::mark_bitmap()->is_marked(this), "should be marked"); @@ -140,13 +105,4 @@ } } -inline void oopDesc::update_header(HeapWord* beg_addr, HeapWord* end_addr) { - if (UseCompressedOops) { - PSParallelCompact::adjust_pointer(compressed_klass_addr(), - beg_addr, end_addr); - } else { - PSParallelCompact::adjust_pointer(klass_addr(), beg_addr, end_addr); - } -} - #endif // SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP
--- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -250,13 +250,6 @@ assert(obj->is_typeArray(),"must be a type array"); return typeArrayOop(obj)->object_size(); } - -int -typeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, - HeapWord* beg_addr, HeapWord* end_addr) { - assert(obj->is_typeArray(),"must be a type array"); - return typeArrayOop(obj)->object_size(); -} #endif // SERIALGC void typeArrayKlass::initialize(TRAPS) {
--- a/hotspot/src/share/vm/opto/escape.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/opto/escape.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,6 +93,9 @@ ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), _processed(C->comp_arena()), + pt_ptset(C->comp_arena()), + pt_visited(C->comp_arena()), + pt_worklist(C->comp_arena(), 4, 0, 0), _collecting(true), _progress(false), _compile(C), @@ -220,9 +223,7 @@ PointsToNode::EscapeState orig_es = es; // compute max escape state of anything this node could point to - VectorSet ptset(Thread::current()->resource_area()); - PointsTo(ptset, n); - for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) { + for(VectorSetI i(PointsTo(n)); i.test() && es != PointsToNode::GlobalEscape; ++i) { uint pt = i.elem; PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); if (pes > es) @@ -236,9 +237,10 @@ return es; } -void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { - VectorSet visited(Thread::current()->resource_area()); - GrowableArray<uint> worklist; +VectorSet* ConnectionGraph::PointsTo(Node * n) { + pt_ptset.Reset(); + pt_visited.Reset(); + pt_worklist.clear(); #ifdef ASSERT Node *orig_n = n; @@ -249,8 +251,8 @@ // If we have a JavaObject, return just that object if (npt->node_type() == PointsToNode::JavaObject) { - ptset.set(n->_idx); - return; + pt_ptset.set(n->_idx); + return &pt_ptset; } #ifdef ASSERT if (npt->_node == NULL) { @@ -260,10 +262,10 @@ assert(npt->_node != NULL, "unregistered node"); } #endif - worklist.push(n->_idx); - while(worklist.length() > 0) { - int ni = worklist.pop(); - if (visited.test_set(ni)) + pt_worklist.push(n->_idx); + while(pt_worklist.length() > 0) { + int ni = pt_worklist.pop(); + if (pt_visited.test_set(ni)) continue; PointsToNode* pn = ptnode_adr(ni); @@ -276,10 +278,10 @@ uint etgt = pn->edge_target(e); PointsToNode::EdgeType et = pn->edge_type(e); if (et == PointsToNode::PointsToEdge) { - ptset.set(etgt); + pt_ptset.set(etgt); edges_processed++; } else if (et == PointsToNode::DeferredEdge) { - worklist.push(etgt); + pt_worklist.push(etgt); edges_processed++; } else { assert(false,"neither PointsToEdge or DeferredEdge"); @@ -288,16 +290,17 @@ if (edges_processed == 0) { // no deferred or pointsto edges found. Assume the value was set // outside this method. Add the phantom object to the pointsto set. - ptset.set(_phantom_object); + pt_ptset.set(_phantom_object); } } + return &pt_ptset; } void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) { // This method is most expensive during ConnectionGraph construction. // Reuse vectorSet and an additional growable array for deferred edges. deferred_edges->clear(); - visited->Clear(); + visited->Reset(); visited->set(ni); PointsToNode *ptn = ptnode_adr(ni); @@ -1009,7 +1012,6 @@ uint new_index_start = (uint) _compile->num_alias_types(); Arena* arena = Thread::current()->resource_area(); VectorSet visited(arena); - VectorSet ptset(arena); // Phase 1: Process possible allocations from alloc_worklist. @@ -1137,10 +1139,9 @@ } } } else if (n->is_AddP()) { - ptset.Clear(); - PointsTo(ptset, get_addp_base(n)); - assert(ptset.Size() == 1, "AddP address is unique"); - uint elem = ptset.getelem(); // Allocation node's index + VectorSet* ptset = PointsTo(get_addp_base(n)); + assert(ptset->Size() == 1, "AddP address is unique"); + uint elem = ptset->getelem(); // Allocation node's index if (elem == _phantom_object) { assert(false, "escaped allocation"); continue; // Assume the value was set outside this method. @@ -1157,10 +1158,9 @@ assert(n->is_Phi(), "loops only through Phi's"); continue; // already processed } - ptset.Clear(); - PointsTo(ptset, n); - if (ptset.Size() == 1) { - uint elem = ptset.getelem(); // Allocation node's index + VectorSet* ptset = PointsTo(n); + if (ptset->Size() == 1) { + uint elem = ptset->getelem(); // Allocation node's index if (elem == _phantom_object) { assert(false, "escaped allocation"); continue; // Assume the value was set outside this method. @@ -1434,7 +1434,7 @@ // Update the memory inputs of MemNodes with the value we computed // in Phase 2 and move stores memory users to corresponding memory slices. #ifdef ASSERT - visited.Clear(); + visited.Reset(); Node_Stack old_mems(arena, _compile->unique() >> 2); #endif for (uint i = 0; i < nodes_size(); i++) { @@ -1640,7 +1640,6 @@ #undef CG_BUILD_ITER_LIMIT Arena* arena = Thread::current()->resource_area(); - VectorSet ptset(arena); VectorSet visited(arena); worklist.clear(); @@ -1657,7 +1656,7 @@ if (n->is_AddP()) { // Search for objects which are not scalar replaceable // and adjust their escape state. - verify_escape_state(ni, ptset, igvn); + adjust_escape_state(ni, igvn); } } } @@ -1776,8 +1775,8 @@ return has_non_escaping_obj; } -// Search for objects which are not scalar replaceable. -void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase) { +// Adjust escape state after Connection Graph is built. +void ConnectionGraph::adjust_escape_state(int nidx, PhaseTransform* phase) { PointsToNode* ptn = ptnode_adr(nidx); Node* n = ptn->_node; assert(n->is_AddP(), "Should be called for AddP nodes only"); @@ -1792,9 +1791,8 @@ int offset = ptn->offset(); Node* base = get_addp_base(n); - ptset.Clear(); - PointsTo(ptset, base); - int ptset_size = ptset.Size(); + VectorSet* ptset = PointsTo(base); + int ptset_size = ptset->Size(); // Check if a oop field's initializing value is recorded and add // a corresponding NULL field's value if it is not recorded. @@ -1814,7 +1812,7 @@ // Do a simple control flow analysis to distinguish above cases. // if (offset != Type::OffsetBot && ptset_size == 1) { - uint elem = ptset.getelem(); // Allocation node's index + uint elem = ptset->getelem(); // Allocation node's index // It does not matter if it is not Allocation node since // only non-escaping allocations are scalar replaced. if (ptnode_adr(elem)->_node->is_Allocate() && @@ -1913,7 +1911,7 @@ // if (ptset_size > 1 || ptset_size != 0 && (has_LoadStore || offset == Type::OffsetBot)) { - for( VectorSetI j(&ptset); j.test(); ++j ) { + for( VectorSetI j(ptset); j.test(); ++j ) { set_escape_state(j.elem, PointsToNode::ArgEscape); ptnode_adr(j.elem)->_scalar_replaceable = false; } @@ -1937,7 +1935,6 @@ // Stub calls, objects do not escape but they are not scale replaceable. // Adjust escape state for outgoing arguments. const TypeTuple * d = call->tf()->domain(); - VectorSet ptset(Thread::current()->resource_area()); for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { const Type* at = d->field_at(i); Node *arg = call->in(i)->uncast(); @@ -1970,9 +1967,7 @@ // arg = get_addp_base(arg); } - ptset.Clear(); - PointsTo(ptset, arg); - for( VectorSetI j(&ptset); j.test(); ++j ) { + for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { uint pt = j.elem; set_escape_state(pt, PointsToNode::ArgEscape); } @@ -1990,7 +1985,6 @@ // fall-through if not a Java method or no analyzer information if (call_analyzer != NULL) { const TypeTuple * d = call->tf()->domain(); - VectorSet ptset(Thread::current()->resource_area()); bool copy_dependencies = false; for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { const Type* at = d->field_at(i); @@ -2015,9 +2009,7 @@ copy_dependencies = true; } - ptset.Clear(); - PointsTo(ptset, arg); - for( VectorSetI j(&ptset); j.test(); ++j ) { + for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { uint pt = j.elem; if (global_escapes) { //The argument global escapes, mark everything it could point to @@ -2045,15 +2037,12 @@ { // adjust escape state for outgoing arguments const TypeTuple * d = call->tf()->domain(); - VectorSet ptset(Thread::current()->resource_area()); for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { const Type* at = d->field_at(i); if (at->isa_oopptr() != NULL) { Node *arg = call->in(i)->uncast(); set_escape_state(arg->_idx, PointsToNode::GlobalEscape); - ptset.Clear(); - PointsTo(ptset, arg); - for( VectorSetI j(&ptset); j.test(); ++j ) { + for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { uint pt = j.elem; set_escape_state(pt, PointsToNode::GlobalEscape); } @@ -2515,9 +2504,7 @@ { Node *base = get_addp_base(n); // Create a field edge to this node from everything base could point to. - VectorSet ptset(Thread::current()->resource_area()); - PointsTo(ptset, base); - for( VectorSetI i(&ptset); i.test(); ++i ) { + for( VectorSetI i(PointsTo(base)); i.test(); ++i ) { uint pt = i.elem; add_field_edge(pt, n_idx, address_offset(n, phase)); } @@ -2583,10 +2570,8 @@ // For everything "adr_base" could point to, create a deferred edge from // this node to each field with the same offset. - VectorSet ptset(Thread::current()->resource_area()); - PointsTo(ptset, adr_base); int offset = address_offset(adr, phase); - for( VectorSetI i(&ptset); i.test(); ++i ) { + for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) { uint pt = i.elem; add_deferred_edge_to_fields(n_idx, pt, offset); } @@ -2676,9 +2661,7 @@ Node *val = n->in(MemNode::ValueIn)->uncast(); // For everything "adr_base" could point to, create a deferred edge // to "val" from each field with the same offset. - VectorSet ptset(Thread::current()->resource_area()); - PointsTo(ptset, adr_base); - for( VectorSetI i(&ptset); i.test(); ++i ) { + for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) { uint pt = i.elem; add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); }
--- a/hotspot/src/share/vm/opto/escape.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/opto/escape.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -268,7 +268,12 @@ // walk the connection graph starting at the node corresponding to "n" and // add the index of everything it could point to, to "ptset". This may cause // Phi's encountered to get (re)processed (which requires "phase".) - void PointsTo(VectorSet &ptset, Node * n); + VectorSet* PointsTo(Node * n); + + // Reused structures for PointsTo(). + VectorSet pt_ptset; + VectorSet pt_visited; + GrowableArray<uint> pt_worklist; // Edge manipulation. The "from_i" and "to_i" arguments are the // node indices of the source and destination of the edge @@ -334,8 +339,11 @@ // Set the escape state of a node void set_escape_state(uint ni, PointsToNode::EscapeState es); - // Search for objects which are not scalar replaceable. - void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase); + // Adjust escape state after Connection Graph is built. + void adjust_escape_state(int nidx, PhaseTransform* phase); + + // Compute the escape information + bool compute_escape(); public: ConnectionGraph(Compile *C, PhaseIterGVN *igvn); @@ -346,9 +354,6 @@ // Perform escape analysis static void do_analysis(Compile *C, PhaseIterGVN *igvn); - // Compute the escape information - bool compute_escape(); - // escape state of a node PointsToNode::EscapeState escape_state(Node *n);
--- a/hotspot/src/share/vm/opto/indexSet.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/opto/indexSet.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,12 +39,12 @@ #ifdef ASSERT // Initialize statistics counters -uint IndexSet::_alloc_new = 0; -uint IndexSet::_alloc_total = 0; +julong IndexSet::_alloc_new = 0; +julong IndexSet::_alloc_total = 0; -long IndexSet::_total_bits = 0; -long IndexSet::_total_used_blocks = 0; -long IndexSet::_total_unused_blocks = 0; +julong IndexSet::_total_bits = 0; +julong IndexSet::_total_used_blocks = 0; +julong IndexSet::_total_unused_blocks = 0; // Per set, or all sets operation tracing int IndexSet::_serial_count = 1; @@ -141,7 +141,7 @@ #ifdef ASSERT if (CollectIndexSetStatistics) { - _alloc_new += bitblock_alloc_chunk_size; + inc_stat_counter(&_alloc_new, bitblock_alloc_chunk_size); } #endif } @@ -154,7 +154,7 @@ IndexSet::BitBlock *IndexSet::alloc_block() { #ifdef ASSERT if (CollectIndexSetStatistics) { - _alloc_total++; + inc_stat_counter(&_alloc_total, 1); } #endif Compile *compile = Compile::current(); @@ -391,13 +391,13 @@ // Update block/bit counts to reflect that this set has been iterated over. void IndexSet::tally_iteration_statistics() const { - _total_bits += count(); + inc_stat_counter(&_total_bits, count()); for (uint i = 0; i < _max_blocks; i++) { if (_blocks[i] != &_empty_block) { - _total_used_blocks++; + inc_stat_counter(&_total_used_blocks, 1); } else { - _total_unused_blocks++; + inc_stat_counter(&_total_unused_blocks, 1); } } } @@ -406,17 +406,17 @@ // Print statistics about IndexSet usage. void IndexSet::print_statistics() { - long total_blocks = _total_used_blocks + _total_unused_blocks; + julong total_blocks = _total_used_blocks + _total_unused_blocks; tty->print_cr ("Accumulated IndexSet usage statistics:"); tty->print_cr ("--------------------------------------"); tty->print_cr (" Iteration:"); - tty->print_cr (" blocks visited: %d", total_blocks); - tty->print_cr (" blocks empty: %4.2f%%", 100.0*_total_unused_blocks/total_blocks); - tty->print_cr (" bit density (bits/used blocks): %4.2f%%", (double)_total_bits/_total_used_blocks); - tty->print_cr (" bit density (bits/all blocks): %4.2f%%", (double)_total_bits/total_blocks); + tty->print_cr (" blocks visited: " UINT64_FORMAT, total_blocks); + tty->print_cr (" blocks empty: %4.2f%%", 100.0*(double)_total_unused_blocks/total_blocks); + tty->print_cr (" bit density (bits/used blocks): %4.2f", (double)_total_bits/_total_used_blocks); + tty->print_cr (" bit density (bits/all blocks): %4.2f", (double)_total_bits/total_blocks); tty->print_cr (" Allocation:"); - tty->print_cr (" blocks allocated: %d", _alloc_new); - tty->print_cr (" blocks used/reused: %d", _alloc_total); + tty->print_cr (" blocks allocated: " UINT64_FORMAT, _alloc_new); + tty->print_cr (" blocks used/reused: " UINT64_FORMAT, _alloc_total); } //---------------------------- IndexSet::verify() -----------------------------
--- a/hotspot/src/share/vm/opto/indexSet.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/opto/indexSet.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -352,13 +352,13 @@ void tally_iteration_statistics() const; // BitBlock allocation statistics - static uint _alloc_new; - static uint _alloc_total; + static julong _alloc_new; + static julong _alloc_total; // Block density statistics - static long _total_bits; - static long _total_used_blocks; - static long _total_unused_blocks; + static julong _total_bits; + static julong _total_used_blocks; + static julong _total_unused_blocks; // Sanity tests void verify() const;
--- a/hotspot/src/share/vm/opto/loopnode.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/opto/loopnode.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1480,6 +1480,8 @@ // Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to // its corresponding LoopNode. If 'optimize' is true, do some loop cleanups. void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool do_loop_pred) { + ResourceMark rm; + int old_progress = C->major_progress(); // Reset major-progress flag for the driver's heuristics @@ -2013,7 +2015,7 @@ if (_dom_stk == NULL) { uint init_size = C->unique() / 100; // Guess that 1/100 is a reasonable initial size. if (init_size < 10) init_size = 10; - _dom_stk = new (C->node_arena()) GrowableArray<uint>(C->node_arena(), init_size, 0, 0); + _dom_stk = new GrowableArray<uint>(init_size); } // Compute new depth for each node. for (i = 0; i < _idom_size; i++) {
--- a/hotspot/src/share/vm/opto/loopnode.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/opto/loopnode.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -700,7 +700,7 @@ PhaseIdealLoop( PhaseIterGVN &igvn) : PhaseTransform(Ideal_Loop), _igvn(igvn), - _dom_lca_tags(C->comp_arena()), + _dom_lca_tags(arena()), // Thread::resource_area _verify_me(NULL), _verify_only(true) { build_and_optimize(false, false); @@ -721,7 +721,7 @@ PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs, bool do_loop_pred) : PhaseTransform(Ideal_Loop), _igvn(igvn), - _dom_lca_tags(C->comp_arena()), + _dom_lca_tags(arena()), // Thread::resource_area _verify_me(NULL), _verify_only(false) { build_and_optimize(do_split_ifs, do_loop_pred); @@ -731,7 +731,7 @@ PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me) : PhaseTransform(Ideal_Loop), _igvn(igvn), - _dom_lca_tags(C->comp_arena()), + _dom_lca_tags(arena()), // Thread::resource_area _verify_me(verify_me), _verify_only(false) { build_and_optimize(false, false);
--- a/hotspot/src/share/vm/opto/node.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/opto/node.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -743,6 +743,9 @@ //------------------------------del_req---------------------------------------- // Delete the required edge and compact the edge array void Node::del_req( uint idx ) { + assert( idx < _cnt, "oob"); + assert( !VerifyHashTableKeys || _hash_lock == 0, + "remove node from hash table before modifying it"); // First remove corresponding def-use edge Node *n = in(idx); if (n != NULL) n->del_out((Node *)this);
--- a/hotspot/src/share/vm/opto/phase.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/opto/phase.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,16 +99,18 @@ tty->print_cr (" stub compilation : %3.3f sec.", Phase::_t_stubCompilation.seconds()); tty->print_cr (" Phases:"); tty->print_cr (" parse : %3.3f sec", Phase::_t_parser.seconds()); - if (DoEscapeAnalysis) { - tty->print_cr (" escape analysis : %3.3f sec", Phase::_t_escapeAnalysis.seconds()); - } tty->print_cr (" optimizer : %3.3f sec", Phase::_t_optimizer.seconds()); if( Verbose || WizardMode ) { + if (DoEscapeAnalysis) { + // EA is part of Optimizer. + tty->print_cr (" escape analysis: %3.3f sec", Phase::_t_escapeAnalysis.seconds()); + } tty->print_cr (" iterGVN : %3.3f sec", Phase::_t_iterGVN.seconds()); tty->print_cr (" idealLoop : %3.3f sec", Phase::_t_idealLoop.seconds()); tty->print_cr (" idealLoopVerify: %3.3f sec", Phase::_t_idealLoopVerify.seconds()); tty->print_cr (" ccp : %3.3f sec", Phase::_t_ccp.seconds()); tty->print_cr (" iterGVN2 : %3.3f sec", Phase::_t_iterGVN2.seconds()); + tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds()); tty->print_cr (" graphReshape : %3.3f sec", Phase::_t_graphReshaping.seconds()); double optimizer_subtotal = Phase::_t_iterGVN.seconds() + Phase::_t_idealLoop.seconds() + Phase::_t_ccp.seconds() + @@ -133,18 +135,15 @@ double percent_of_regalloc = ((regalloc_subtotal == 0.0) ? 0.0 : (regalloc_subtotal / Phase::_t_registerAllocation.seconds() * 100.0)); tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc); } - tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds()); tty->print_cr (" blockOrdering : %3.3f sec", Phase::_t_blockOrdering.seconds()); tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds()); tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds()); tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds()); tty->print_cr (" -------------- : ----------"); double phase_subtotal = Phase::_t_parser.seconds() + - (DoEscapeAnalysis ? Phase::_t_escapeAnalysis.seconds() : 0.0) + Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() + Phase::_t_matcher.seconds() + Phase::_t_scheduler.seconds() + Phase::_t_registerAllocation.seconds() + Phase::_t_blockOrdering.seconds() + - Phase::_t_macroExpand.seconds() + Phase::_t_peephole.seconds() + Phase::_t_codeGeneration.seconds() + Phase::_t_registerMethod.seconds(); double percent_of_method_compile = ((phase_subtotal == 0.0) ? 0.0 : phase_subtotal / Phase::_t_methodCompilation.seconds()) * 100.0; // counters inside Compile::CodeGen include time for adapters and stubs
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1247,12 +1247,12 @@ // Constant pools are not easily reused so we allocate a new one // each time. // merge_cp is created unsafe for concurrent GC processing. It - // should be marked safe before discarding it because, even if - // garbage. If it crosses a card boundary, it may be scanned + // should be marked safe before discarding it. Even though + // garbage, if it crosses a card boundary, it may be scanned // in order to find the start of the first complete object on the card. constantPoolHandle merge_cp(THREAD, oopFactory::new_constantPool(merge_cp_length, - methodOopDesc::IsUnsafeConc, + oopDesc::IsUnsafeConc, THREAD)); int orig_length = old_cp->orig_length(); if (orig_length == 0) { @@ -2343,7 +2343,7 @@ // sized constant pool with the klass to save space. constantPoolHandle smaller_cp(THREAD, oopFactory::new_constantPool(scratch_cp_length, - methodOopDesc::IsUnsafeConc, + oopDesc::IsUnsafeConc, THREAD)); // preserve orig_length() value in the smaller copy int orig_length = scratch_cp->orig_length();
--- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1134,8 +1134,9 @@ constantPoolHandle MethodHandleCompiler::get_constant_pool(TRAPS) const { constantPoolHandle nullHandle; - bool is_conc_safe = true; - constantPoolOop cpool_oop = oopFactory::new_constantPool(_constants.length(), is_conc_safe, CHECK_(nullHandle)); + constantPoolOop cpool_oop = oopFactory::new_constantPool(_constants.length(), + oopDesc::IsSafeConc, + CHECK_(nullHandle)); constantPoolHandle cpool(THREAD, cpool_oop); // Fill the real constant pool skipping the zero element. @@ -1180,10 +1181,9 @@ else flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SYNTHETIC); - bool is_conc_safe = true; methodOop m_oop = oopFactory::new_method(bytecode_length(), accessFlags_from(flags_bits), - 0, 0, 0, is_conc_safe, CHECK_(nullHandle)); + 0, 0, 0, oopDesc::IsSafeConc, CHECK_(nullHandle)); methodHandle m(THREAD, m_oop); m_oop = NULL; // oop not GC safe
--- a/hotspot/src/share/vm/runtime/arguments.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1410,7 +1410,7 @@ // by ergonomics. if (MaxHeapSize <= max_heap_for_compressed_oops()) { #if !defined(COMPILER1) || defined(TIERED) - if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) { + if (FLAG_IS_DEFAULT(UseCompressedOops)) { FLAG_SET_ERGO(bool, UseCompressedOops, true); } #endif @@ -3103,6 +3103,19 @@ // Set flags if Aggressive optimization flags (-XX:+AggressiveOpts) enabled. set_aggressive_opts_flags(); + // Turn off biased locking for locking debug mode flags, + // which are subtlely different from each other but neither works with + // biased locking. + if (!UseFastLocking || UseHeavyMonitors) { + if (!FLAG_IS_DEFAULT(UseBiasedLocking) && UseBiasedLocking) { + // flag set to true on command line; warn the user that they + // can't enable biased locking here + warning("Biased Locking is not supported with locking debug flags" + "; ignoring UseBiasedLocking flag." ); + } + UseBiasedLocking = false; + } + #ifdef CC_INTERP // Clear flags not supported by the C++ interpreter FLAG_SET_DEFAULT(ProfileInterpreter, false);
--- a/hotspot/src/share/vm/runtime/globals.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/runtime/globals.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -740,6 +740,9 @@ develop(bool, PrintMalloc, false, \ "print all malloc/free calls") \ \ + develop(bool, PrintMallocStatistics, false, \ + "print malloc/free statistics") \ + \ develop(bool, ZapResourceArea, trueInDebug, \ "Zap freed resource/arena space with 0xABABABAB") \ \ @@ -2664,25 +2667,6 @@ product(bool, UseStringCache, false, \ "Enable String cache capabilities on String.java") \ \ - /* byte strings */ \ - product(bool, UseCompressedStrings, false, \ - "Enable byte-valued strings") \ - \ - product(bool, SpecialStringCompress, true, \ - "special version of string compress") \ - \ - product(bool, SpecialStringInflate, true, \ - "special version of string inflate") \ - \ - product(bool, SpecialStringCompareToCC, true, \ - "special version of string compareToCC") \ - \ - product(bool, SpecialStringIndexOfCC, true, \ - "special version of string indexOfCC") \ - \ - product(bool, SpecialStringEqualsCC, true, \ - "special version of string equalsCC") \ - \ /* statistics */ \ develop(bool, CountCompiledCalls, false, \ "counts method invocations") \ @@ -3692,7 +3676,7 @@ product(uintx, SharedReadOnlySize, 10*M, \ "Size of read-only space in permanent generation (in bytes)") \ \ - product(uintx, SharedMiscDataSize, 4*M, \ + product(uintx, SharedMiscDataSize, NOT_LP64(4*M) LP64_ONLY(5*M), \ "Size of the shared data area adjacent to the heap (in bytes)") \ \ product(uintx, SharedMiscCodeSize, 4*M, \
--- a/hotspot/src/share/vm/runtime/java.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/runtime/java.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -326,7 +326,7 @@ } print_bytecode_count(); - if (WizardMode) { + if (PrintMallocStatistics) { tty->print("allocation stats: "); alloc_stats.print(); tty->cr();
--- a/hotspot/src/share/vm/runtime/os.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/runtime/os.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,9 +72,10 @@ size_t os::_page_sizes[os::page_sizes_max]; #ifndef PRODUCT -int os::num_mallocs = 0; // # of calls to malloc/realloc -size_t os::alloc_bytes = 0; // # of bytes allocated -int os::num_frees = 0; // # of calls to free +julong os::num_mallocs = 0; // # of calls to malloc/realloc +julong os::alloc_bytes = 0; // # of bytes allocated +julong os::num_frees = 0; // # of calls to free +julong os::free_bytes = 0; // # of bytes freed #endif // Fill in buffer with current local time as an ISO-8601 string. @@ -490,9 +491,9 @@ } if (start_of_prev_block + space_before + size + space_after == start_of_this_block) { - tty->print_cr("### previous object: %p (%ld bytes)", obj, size); + tty->print_cr("### previous object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size); } else { - tty->print_cr("### previous object (not sure if correct): %p (%ld bytes)", obj, size); + tty->print_cr("### previous object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size); } // now find successor block @@ -504,16 +505,16 @@ start_of_next_block[1] == badResourceValue && start_of_next_block[2] == badResourceValue && start_of_next_block[3] == badResourceValue) { - tty->print_cr("### next object: %p (%ld bytes)", next_obj, next_size); + tty->print_cr("### next object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size); } else { - tty->print_cr("### next object (not sure if correct): %p (%ld bytes)", next_obj, next_size); + tty->print_cr("### next object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size); } } void report_heap_error(void* memblock, void* bad, const char* where) { - tty->print_cr("## nof_mallocs = %d, nof_frees = %d", os::num_mallocs, os::num_frees); - tty->print_cr("## memory stomp: byte at %p %s object %p", bad, where, memblock); + tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees); + tty->print_cr("## memory stomp: byte at " PTR_FORMAT " %s object " PTR_FORMAT, bad, where, memblock); print_neighbor_blocks(memblock); fatal("memory stomping error"); } @@ -538,8 +539,8 @@ #endif void* os::malloc(size_t size) { - NOT_PRODUCT(num_mallocs++); - NOT_PRODUCT(alloc_bytes += size); + NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); + NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); if (size == 0) { // return a valid pointer if size is zero @@ -562,26 +563,26 @@ #endif u_char* memblock = ptr + space_before; if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { - tty->print_cr("os::malloc caught, %lu bytes --> %p", size, memblock); + tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock); breakpoint(); } debug_only(if (paranoid) verify_block(memblock)); - if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc %lu bytes --> %p", size, memblock); + if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock); return memblock; } void* os::realloc(void *memblock, size_t size) { - NOT_PRODUCT(num_mallocs++); - NOT_PRODUCT(alloc_bytes += size); #ifndef ASSERT + NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); + NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); return ::realloc(memblock, size); #else if (memblock == NULL) { - return os::malloc(size); + return malloc(size); } if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { - tty->print_cr("os::realloc caught %p", memblock); + tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); breakpoint(); } verify_block(memblock); @@ -589,13 +590,13 @@ if (size == 0) return NULL; // always move the block void* ptr = malloc(size); - if (PrintMalloc) tty->print_cr("os::remalloc %lu bytes, %p --> %p", size, memblock, ptr); + if (PrintMalloc) tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); // Copy to new memory if malloc didn't fail if ( ptr != NULL ) { memcpy(ptr, memblock, MIN2(size, get_size(memblock))); if (paranoid) verify_block(ptr); if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { - tty->print_cr("os::realloc caught, %lu bytes --> %p", size, ptr); + tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); breakpoint(); } free(memblock); @@ -606,17 +607,14 @@ void os::free(void *memblock) { - NOT_PRODUCT(num_frees++); + NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); #ifdef ASSERT if (memblock == NULL) return; if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { - if (tty != NULL) tty->print_cr("os::free caught %p", memblock); + if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); breakpoint(); } verify_block(memblock); - if (PrintMalloc && tty != NULL) - // tty->print_cr("os::free %p", memblock); - fprintf(stderr, "os::free %p\n", memblock); NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); // Added by detlefs. if (MallocCushion) { @@ -627,12 +625,18 @@ *p = (u_char)freeBlockPad; } size_t size = get_size(memblock); + inc_stat_counter(&free_bytes, size); u_char* end = ptr + space_before + size; for (u_char* q = end; q < end + MallocCushion; q++) { guarantee(*q == badResourceValue, "Thing freed should be malloc result."); *q = (u_char)freeBlockPad; } + if (PrintMalloc && tty != NULL) + fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, memblock); + } else if (PrintMalloc && tty != NULL) { + // tty->print_cr("os::free %p", memblock); + fprintf(stderr, "os::free " PTR_FORMAT "\n", memblock); } #endif ::free((char*)memblock - space_before);
--- a/hotspot/src/share/vm/runtime/os.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/runtime/os.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -559,9 +559,10 @@ static char* strdup(const char *); // Like strdup #ifndef PRODUCT - static int num_mallocs; // # of calls to malloc/realloc - static size_t alloc_bytes; // # of bytes allocated - static int num_frees; // # of calls to free + static julong num_mallocs; // # of calls to malloc/realloc + static julong alloc_bytes; // # of bytes allocated + static julong num_frees; // # of calls to free + static julong free_bytes; // # of bytes freed #endif // SocketInterface (ex HPI SocketInterface )
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "runtime/arguments.hpp" #include "runtime/simpleThresholdPolicy.hpp" #include "runtime/simpleThresholdPolicy.inline.hpp" +#include "code/scopeDesc.hpp" // Print an event. void SimpleThresholdPolicy::print_event(EventType type, methodHandle mh, methodHandle imh, @@ -48,6 +49,18 @@ break; case COMPILE: tty->print("compile"); + break; + case KILL: + tty->print("kill"); + break; + case UPDATE: + tty->print("update"); + break; + case REPROFILE: + tty->print("reprofile"); + break; + default: + tty->print("unknown"); } tty->print(" level: %d ", level); @@ -69,13 +82,17 @@ if (type != COMPILE) { methodDataHandle mdh = mh->method_data(); int mdo_invocations = 0, mdo_backedges = 0; + int mdo_invocations_start = 0, mdo_backedges_start = 0; if (mdh() != NULL) { mdo_invocations = mdh->invocation_count(); mdo_backedges = mdh->backedge_count(); + mdo_invocations_start = mdh->invocation_count_start(); + mdo_backedges_start = mdh->backedge_count_start(); } - tty->print(" total: %d,%d mdo: %d,%d", + tty->print(" total: %d,%d mdo: %d(%d),%d(%d)", invocation_count, backedge_count, - mdo_invocations, mdo_backedges); + mdo_invocations, mdo_invocations_start, + mdo_backedges, mdo_backedges_start); tty->print(" max levels: %d,%d", mh->highest_comp_level(), mh->highest_osr_comp_level()); if (inlinee_event) { @@ -138,6 +155,20 @@ return compile_queue->first(); } +void SimpleThresholdPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) { + for (ScopeDesc* sd = trap_scope;; sd = sd->sender()) { + if (PrintTieredEvents) { + methodHandle mh(sd->method()); + print_event(REPROFILE, mh, mh, InvocationEntryBci, CompLevel_none); + } + methodDataOop mdo = sd->method()->method_data(); + if (mdo != NULL) { + mdo->reset_start_counters(); + } + if (sd->is_top()) break; + } +} + nmethod* SimpleThresholdPolicy::event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, TRAPS) { if (comp_level == CompLevel_none && @@ -254,46 +285,35 @@ // Common transition function. Given a predicate determines if a method should transition to another level. CompLevel SimpleThresholdPolicy::common(Predicate p, methodOop method, CompLevel cur_level) { + if (is_trivial(method)) return CompLevel_simple; + CompLevel next_level = cur_level; int i = method->invocation_count(); int b = method->backedge_count(); switch(cur_level) { case CompLevel_none: - { - methodDataOop mdo = method->method_data(); - if (mdo != NULL) { - int mdo_i = mdo->invocation_count(); - int mdo_b = mdo->backedge_count(); - // If we were at full profile level, would we switch to full opt? - if ((this->*p)(mdo_i, mdo_b, CompLevel_full_profile)) { - next_level = CompLevel_full_optimization; - } - } - } - if (next_level == cur_level && (this->*p)(i, b, cur_level)) { - if (is_trivial(method)) { - next_level = CompLevel_simple; - } else { - next_level = CompLevel_full_profile; - } + // If we were at full profile level, would we switch to full opt? + if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) { + next_level = CompLevel_full_optimization; + } else if ((this->*p)(i, b, cur_level)) { + next_level = CompLevel_full_profile; } break; case CompLevel_limited_profile: case CompLevel_full_profile: - if (is_trivial(method)) { - next_level = CompLevel_simple; - } else { + { methodDataOop mdo = method->method_data(); - guarantee(mdo != NULL, "MDO should always exist"); - if (mdo->would_profile()) { - int mdo_i = mdo->invocation_count(); - int mdo_b = mdo->backedge_count(); - if ((this->*p)(mdo_i, mdo_b, cur_level)) { + if (mdo != NULL) { + if (mdo->would_profile()) { + int mdo_i = mdo->invocation_count_delta(); + int mdo_b = mdo->backedge_count_delta(); + if ((this->*p)(mdo_i, mdo_b, cur_level)) { + next_level = CompLevel_full_optimization; + } + } else { next_level = CompLevel_full_optimization; } - } else { - next_level = CompLevel_full_optimization; } } break; @@ -303,12 +323,6 @@ // Determine if a method should be compiled with a normal entry point at a different level. CompLevel SimpleThresholdPolicy::call_event(methodOop method, CompLevel cur_level) { - CompLevel highest_level = (CompLevel)method->highest_comp_level(); - if (cur_level == CompLevel_none && highest_level > cur_level) { - // TODO: We may want to try to do more extensive reprofiling in this case. - return highest_level; - } - CompLevel osr_level = (CompLevel) method->highest_osr_comp_level(); CompLevel next_level = common(&SimpleThresholdPolicy::call_predicate, method, cur_level);
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ void set_c1_count(int x) { _c1_count = x; } void set_c2_count(int x) { _c2_count = x; } - enum EventType { CALL, LOOP, COMPILE }; + enum EventType { CALL, LOOP, COMPILE, KILL, UPDATE, REPROFILE }; void print_event(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level); // Print policy-specific information if necessary virtual void print_specific(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level) { } @@ -103,7 +103,7 @@ virtual void disable_compilation(methodOop method) { } // TODO: we should honour reprofiling requests in the future. Currently reprofiling // would happen but not to the extent we would ideally like. - virtual void reprofile(ScopeDesc* trap_scope, bool is_osr) { } + virtual void reprofile(ScopeDesc* trap_scope, bool is_osr); virtual nmethod* event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, TRAPS); // Select task is called by CompileBroker. We should return a task or NULL.
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -748,7 +748,6 @@ /***********************************/ \ \ static_field(StubRoutines, _call_stub_return_address, address) \ - IA32_ONLY(static_field(StubRoutines::x86,_call_stub_compiled_return, address)) \ \ /***************************************/ \ /* PcDesc and other compiled code info */ \
--- a/hotspot/src/share/vm/services/heapDumper.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/services/heapDumper.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1397,6 +1397,7 @@ public: VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump, bool oome) : VM_GC_Operation(0 /* total collections, dummy, ignored */, + GCCause::_heap_dump /* GC Cause */, 0 /* total full collections, dummy, ignored */, gc_before_heap_dump) { _local_writer = writer;
--- a/hotspot/src/share/vm/services/management.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/services/management.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -1311,7 +1311,7 @@ if (locked_monitors) { // Constructs Object[] and int[] to contain the object monitor and the stack depth // where the thread locked it - objArrayOop array = oopFactory::new_system_objArray(num_locked_monitors, CHECK_NULL); + objArrayOop array = oopFactory::new_objArray(SystemDictionary::Object_klass(), num_locked_monitors, CHECK_NULL); objArrayHandle mh(THREAD, array); monitors_array = mh; @@ -1353,7 +1353,7 @@ GrowableArray<instanceOop>* locks = (tcl != NULL ? tcl->owned_locks() : NULL); int num_locked_synchronizers = (locks != NULL ? locks->length() : 0); - objArrayOop array = oopFactory::new_system_objArray(num_locked_synchronizers, CHECK_NULL); + objArrayOop array = oopFactory::new_objArray(SystemDictionary::Object_klass(), num_locked_synchronizers, CHECK_NULL); objArrayHandle sh(THREAD, array); synchronizers_array = sh;
--- a/hotspot/src/share/vm/utilities/errorReporter.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/utilities/errorReporter.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -26,6 +26,7 @@ #define SHARE_VM_UTILITIES_ERRORREPORTER_HPP #include "utilities/globalDefinitions.hpp" +#include "memory/allocation.hpp" class ErrorReporter : public StackObj {
--- a/hotspot/src/share/vm/utilities/hashtable.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/utilities/hashtable.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -276,7 +276,7 @@ } int index_for(Symbol* name, Handle loader) { - return hash_to_index(compute_hash(name, loader)); + return this->hash_to_index(compute_hash(name, loader)); } };
--- a/hotspot/src/share/vm/utilities/ostream.cpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/utilities/ostream.cpp Sun Mar 06 20:32:49 2011 -0800 @@ -699,6 +699,17 @@ defaultStream::instance->release(holder); } +bool ttyLocker::release_tty_if_locked() { + intx thread_id = os::current_thread_id(); + if (defaultStream::instance->writer() == thread_id) { + // release the lock and return true so callers know if was + // previously held. + release_tty(thread_id); + return true; + } + return false; +} + void ttyLocker::break_tty_lock_for_safepoint(intx holder) { if (defaultStream::instance != NULL && defaultStream::instance->writer() == holder) {
--- a/hotspot/src/share/vm/utilities/ostream.hpp Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/src/share/vm/utilities/ostream.hpp Sun Mar 06 20:32:49 2011 -0800 @@ -123,18 +123,36 @@ // advisory locking for the shared tty stream: class ttyLocker: StackObj { + friend class ttyUnlocker; private: intx _holder; public: static intx hold_tty(); // returns a "holder" token static void release_tty(intx holder); // must witness same token + static bool release_tty_if_locked(); // returns true if lock was released static void break_tty_lock_for_safepoint(intx holder); ttyLocker() { _holder = hold_tty(); } ~ttyLocker() { release_tty(_holder); } }; +// Release the tty lock if it's held and reacquire it if it was +// locked. Used to avoid lock ordering problems. +class ttyUnlocker: StackObj { + private: + bool _was_locked; + public: + ttyUnlocker() { + _was_locked = ttyLocker::release_tty_if_locked(); + } + ~ttyUnlocker() { + if (_was_locked) { + ttyLocker::hold_tty(); + } + } +}; + // for writing to strings; buffer will expand automatically class stringStream : public outputStream { protected:
--- a/hotspot/test/compiler/6987555/Test6987555.java Tue Mar 01 15:24:46 2011 +0300 +++ b/hotspot/test/compiler/6987555/Test6987555.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,8 +54,8 @@ if (DEBUG) System.out.println("boolean=" + x); MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(boolean.class, boolean.class)); MethodHandle mh2 = mh1.asType(MethodType.methodType(boolean.class, Boolean.class)); - boolean a = mh1.<boolean>invokeExact(x); - boolean b = mh2.<boolean>invokeExact(Boolean.valueOf(x)); + boolean a = (boolean) mh1.invokeExact(x); + boolean b = (boolean) mh2.invokeExact(Boolean.valueOf(x)); assert a == b : a + " != " + b; } @@ -80,8 +80,8 @@ if (DEBUG) System.out.println("byte=" + x); MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(byte.class, byte.class)); MethodHandle mh2 = mh1.asType(MethodType.methodType(byte.class, Byte.class)); - byte a = mh1.<byte>invokeExact(x); - byte b = mh2.<byte>invokeExact(Byte.valueOf(x)); + byte a = (byte) mh1.invokeExact(x); + byte b = (byte) mh2.invokeExact(Byte.valueOf(x)); assert a == b : a + " != " + b; } @@ -104,8 +104,8 @@ if (DEBUG) System.out.println("char=" + x); MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(char.class, char.class)); MethodHandle mh2 = mh1.asType(MethodType.methodType(char.class, Character.class)); - char a = mh1.<char>invokeExact(x); - char b = mh2.<char>invokeExact(Character.valueOf(x)); + char a = (char) mh1.invokeExact(x); + char b = (char) mh2.invokeExact(Character.valueOf(x)); assert a == b : a + " != " + b; } @@ -134,8 +134,8 @@ if (DEBUG) System.out.println("short=" + x); MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(short.class, short.class)); MethodHandle mh2 = mh1.asType(MethodType.methodType(short.class, Short.class)); - short a = mh1.<short>invokeExact(x); - short b = mh2.<short>invokeExact(Short.valueOf(x)); + short a = (short) mh1.invokeExact(x); + short b = (short) mh2.invokeExact(Short.valueOf(x)); assert a == b : a + " != " + b; } @@ -164,8 +164,8 @@ if (DEBUG) System.out.println("int=" + x); MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(int.class, int.class)); MethodHandle mh2 = mh1.asType(MethodType.methodType(int.class, Integer.class)); - int a = mh1.<int>invokeExact(x); - int b = mh2.<int>invokeExact(Integer.valueOf(x)); + int a = (int) mh1.invokeExact(x); + int b = (int) mh2.invokeExact(Integer.valueOf(x)); assert a == b : a + " != " + b; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/7017746/Test.java Sun Mar 06 20:32:49 2011 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7017746 + * @summary Regression : C2 compiler crash due to SIGSEGV in PhaseCFG::schedule_early() + * + * @run main/othervm -Xbatch Test + */ + +public class Test { + + int i; + + static int test(Test t, int a, int b) { + int j = t.i; + int x = a - b; + if (a < b) x = x + j; + return x - j; + } + + public static void main(String args[]) { + Test t = new Test(); + for (int n = 0; n < 1000000; n++) { + int i = test(t, 1, 2); + } + } +} +
--- a/jaxp/.hgtags Tue Mar 01 15:24:46 2011 +0300 +++ b/jaxp/.hgtags Sun Mar 06 20:32:49 2011 -0800 @@ -105,3 +105,4 @@ a42c6132c746c86e9fc27ec80cbd699f6ee5edca jdk7-b128 f5b60c5a310f992c6ca627d17ca3e042f0e0b2c3 jdk7-b129 ab107c1bc4b918404b191838c455e9b2892389f3 jdk7-b130 +eab6f27131e4e2f0af0016b35b18ae65cdd249d9 jdk7-b131
--- a/jaxws/.hgtags Tue Mar 01 15:24:46 2011 +0300 +++ b/jaxws/.hgtags Sun Mar 06 20:32:49 2011 -0800 @@ -105,3 +105,4 @@ 88d74afc55938033e744b537a22714bb2c82c9c0 jdk7-b128 0f7b39ad902424e949e3d2dca8411b884888a76f jdk7-b129 ba1fac1c2083196422a12130db174334179a4d44 jdk7-b130 +438abc0356cd97d91b25f67cd1abc9883e22f6ed jdk7-b131
--- a/jdk/.hgtags Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/.hgtags Sun Mar 06 20:32:49 2011 -0800 @@ -106,3 +106,4 @@ 14cd5d54a8d0b9c368d60ea83a066735b9931015 jdk7-b129 bdc069d3f9101f89ec3f81c2950ee2d68fa846d3 jdk7-b130 8ac52c85f9e91336dc00b52ef90b42eecf3230b3 jdk7-b131 +6bbc7a4734952ae7604578f270e1566639fa8752 jdk7-b132
--- a/jdk/make/java/security/Makefile Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/make/java/security/Makefile Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1996, 2010 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1996, 2011 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -65,6 +65,8 @@ ifndef OPENJDK BLACKLIST_SRC = $(CLOSED_SHARE_SRC)/lib/security/blacklist BLACKLIST_BUILD = $(LIBDIR)/security/blacklist + TRUSTEDLIBS_SRC = $(CLOSED_SHARE_SRC)/lib/security/trusted.libraries + TRUSTEDLIBS_BUILD = $(LIBDIR)/security/trusted.libraries endif FILES_class = $(FILES_java:%.java=$(CLASSBINDIR)/%.class) @@ -77,7 +79,7 @@ ifdef OPENJDK build: properties policy cacerts else -build: properties policy cacerts blacklist +build: properties policy cacerts blacklist trustedlibs endif install: all @@ -90,6 +92,8 @@ blacklist: classes $(BLACKLIST_BUILD) +trustedlibs: classes $(TRUSTEDLIBS_BUILD) + $(PROPS_BUILD): $(PROPS_SRC) $(install-file) @@ -102,9 +106,12 @@ $(BLACKLIST_BUILD): $(BLACKLIST_SRC) $(install-file) +$(TRUSTEDLIBS_BUILD): $(TRUSTEDLIBS_SRC) + $(install-file) + clean clobber:: .delete.classlist $(RM) -r $(CLASSBINDIR)/java/security - $(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD) $(BLACKLIST_BUILD) + $(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD) $(BLACKLIST_BUILD) $(TRUSTEDLIBS_BUILD) # Additional Rule for building sun.security.util $(CLASSBINDIR)/%.class: $(SHARE_SRC)/sun/%.java
--- a/jdk/make/sun/javazic/tzdata/VERSION Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/make/sun/javazic/tzdata/VERSION Sun Mar 06 20:32:49 2011 -0800 @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2010o +tzdata2011b
--- a/jdk/make/sun/javazic/tzdata/australasia Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/make/sun/javazic/tzdata/australasia Sun Mar 06 20:32:49 2011 -0800 @@ -106,14 +106,13 @@ Rule AS 1987 2007 - Oct lastSun 2:00s 1:00 - Rule AS 1972 only - Feb 27 2:00s 0 - Rule AS 1973 1985 - Mar Sun>=1 2:00s 0 - -Rule AS 1986 1989 - Mar Sun>=15 2:00s 0 - -Rule AS 1990 only - Mar Sun>=18 2:00s 0 - -Rule AS 1991 only - Mar Sun>=1 2:00s 0 - -Rule AS 1992 only - Mar Sun>=18 2:00s 0 - -Rule AS 1993 only - Mar Sun>=1 2:00s 0 - -Rule AS 1994 only - Mar Sun>=18 2:00s 0 - +Rule AS 1986 1990 - Mar Sun>=15 2:00s 0 - +Rule AS 1991 only - Mar 3 2:00s 0 - +Rule AS 1992 only - Mar 22 2:00s 0 - +Rule AS 1993 only - Mar 7 2:00s 0 - +Rule AS 1994 only - Mar 20 2:00s 0 - Rule AS 1995 2005 - Mar lastSun 2:00s 0 - -Rule AS 2006 only - Apr Sun>=1 2:00s 0 - +Rule AS 2006 only - Apr 2 2:00s 0 - Rule AS 2007 only - Mar lastSun 2:00s 0 - Rule AS 2008 max - Apr Sun>=1 2:00s 0 - Rule AS 2008 max - Oct Sun>=1 2:00s 1:00 -
--- a/jdk/make/sun/javazic/tzdata/northamerica Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/make/sun/javazic/tzdata/northamerica Sun Mar 06 20:32:49 2011 -0800 @@ -368,6 +368,27 @@ -7:00 US M%sT 2003 Oct 26 02:00 -6:00 US C%sT +# From Josh Findley (2011-01-21): +# ...it appears that Mercer County, North Dakota, changed from the +# mountain time zone to the central time zone at the last transition from +# daylight-saving to standard time (on Nov. 7, 2010): +# <a href="http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm"> +# http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm +# </a> +# <a href="http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html"> +# http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html +# </a> + +# From Andy Lipscomb (2011-01-24): +# ...according to the Census Bureau, the largest city is Beulah (although +# it's commonly referred to as Beulah-Hazen, with Hazen being the next +# largest city in Mercer County). Google Maps places Beulah's city hall +# at 4715'51" north, 10146'40" west, which yields an offset of 6h47'07". + +Zone America/North_Dakota/Beulah -6:47:07 - LMT 1883 Nov 18 12:12:53 + -7:00 US M%sT 2010 Nov 7 2:00 + -6:00 US C%sT + # US mountain time, represented by Denver # # Colorado, far western Kansas, Montana, western @@ -493,20 +514,50 @@ # three votes for and one against." # Hawaii -# -# From Arthur David Olson: -# And then there's Hawaii. -# DST was observed for one day in 1933; -# standard time was changed by half an hour in 1947; -# it's always standard as of 1986. + +# From Arthur David Olson (2010-12-09): +# "Hawaiian Time" by Robert C. Schmitt and Doak C. Cox appears on pages 207-225 +# of volume 26 of The Hawaiian Journal of History (1992). As of 2010-12-09, +# the article is available at +# <a href="http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf"> +# http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf +# </a> +# and indicates that standard time was adopted effective noon, January +# 13, 1896 (page 218), that in "1933, the Legislature decreed daylight +# saving for the period between the last Sunday of each April and the +# last Sunday of each September, but less than a month later repealed the +# act," (page 220), that year-round daylight saving time was in effect +# from 1942-02-09 to 1945-09-30 (page 221, with no time of day given for +# when clocks changed) and that clocks were changed by 30 minutes +# effective the second Sunday of June, 1947 (page 219, with no time of +# day given for when clocks changed). A footnote for the 1933 changes +# cites Session Laws of Hawaii 1933, "Act. 90 (approved 26 Apr. 1933) +# and Act 163 (approved 21 May 1933)." + +# From Arthur David Olson (2011-01-19): +# The following is from "Laws of the Territory of Hawaii Passed by the +# Seventeenth Legislature: Regular Session 1933," available (as of +# 2011-01-19) at American University's Pence Law Library. Page 85: "Act +# 90...At 2 o'clock ante meridian of the last Sunday in April of each +# year, the standard time of this Territory shall be advanced one +# hour...This Act shall take effect upon its approval. Approved this 26th +# day of April, A. D. 1933. LAWRENCE M JUDD, Governor of the Territory of +# Hawaii." Page 172: "Act 163...Act 90 of the Session Laws of 1933 is +# hereby repealed...This Act shall take effect upon its approval, upon +# which date the standard time of this Territory shall be restored to +# that existing immediately prior to the taking effect of said Act 90. +# Approved this 21st day of May, A. D. 1933. LAWRENCE M. JUDD, Governor +# of the Territory of Hawaii." # -# From Paul Eggert: -# Shanks says the 1933 experiment lasted for three weeks. Go with Shanks. -# -Zone Pacific/Honolulu -10:31:26 - LMT 1900 Jan 1 12:00 - -10:30 - HST 1933 Apr 30 2:00 - -10:30 1:00 HDT 1933 May 21 2:00 - -10:30 US H%sT 1947 Jun 8 2:00 +# Note that 1933-05-21 was a Sunday. +# We're left to guess the time of day when Act 163 was approved; guess noon. + +Zone Pacific/Honolulu -10:31:26 - LMT 1896 Jan 13 12:00 #Schmitt&Cox + -10:30 - HST 1933 Apr 30 2:00 #Laws 1933 + -10:30 1:00 HDT 1933 May 21 12:00 #Laws 1933+12 + -10:30 - HST 1942 Feb 09 2:00 #Schmitt&Cox+2 + -10:30 1:00 HDT 1945 Sep 30 2:00 #Schmitt&Fox+2 + -10:30 US H%sT 1947 Jun 8 2:00 #Schmitt&Fox+2 -10:00 - HST # Now we turn to US areas that have diverged from the consensus since 1970.
--- a/jdk/make/sun/javazic/tzdata/zone.tab Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/make/sun/javazic/tzdata/zone.tab Sun Mar 06 20:32:49 2011 -0800 @@ -233,8 +233,8 @@ HU +4730+01905 Europe/Budapest ID -0610+10648 Asia/Jakarta Java & Sumatra ID -0002+10920 Asia/Pontianak west & central Borneo -ID -0507+11924 Asia/Makassar east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor -ID -0232+14042 Asia/Jayapura Irian Jaya & the Moluccas +ID -0507+11924 Asia/Makassar east & south Borneo, Sulawesi (Celebes), Bali, Nusa Tengarra, west Timor +ID -0232+14042 Asia/Jayapura west New Guinea (Irian Jaya) & Malukus (Moluccas) IE +5320-00615 Europe/Dublin IL +3146+03514 Asia/Jerusalem IM +5409-00428 Europe/Isle_of_Man @@ -426,6 +426,7 @@ US +450628-0873651 America/Menominee Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties US +470659-1011757 America/North_Dakota/Center Central Time - North Dakota - Oliver County US +465042-1012439 America/North_Dakota/New_Salem Central Time - North Dakota - Morton County (except Mandan area) +US +471551-1014640 America/North_Dakota/Beulah Central Time - North Dakota - Mercer County US +394421-1045903 America/Denver Mountain Time US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon US +364708-1084111 America/Shiprock Mountain Time - Navajo
--- a/jdk/make/sun/jpeg/Makefile Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/make/sun/jpeg/Makefile Sun Mar 06 20:32:49 2011 -0800 @@ -65,6 +65,19 @@ FILES_reorder += reorder-$(ARCH) endif endif + +ifeq ($(PLATFORM), linux) + + # Suppress gcc warnings like "variable might be clobbered by 'longjmp' + # or 'vfork'": this warning indicates that some variable is placed to + # a register by optimized compiler and it's value might be lost on longjmp(). + # Recommended way to avoid such warning is to declare the variable as + # volatile to prevent the optimization. However, this approach does not + # work because we have to declare all variables as volatile in result. + + OTHER_CFLAGS += -Wno-clobbered +endif + include $(BUILDDIR)/common/Mapfile-vers.gmk include $(BUILDDIR)/common/Library.gmk
--- a/jdk/make/sun/jpeg/reorder-i586 Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/make/sun/jpeg/reorder-i586 Sun Mar 06 20:32:49 2011 -0800 @@ -22,7 +22,7 @@ text: .text%alloc_small: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o; text: .text%reset_marker_reader: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jIInCtlr; -text: .text%GET_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; +# text: .text%GET_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; text: .text%jReadHeader; text: .text%jConsumeInput; text: .text%reset_input_controller: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; @@ -30,36 +30,36 @@ text: .text%sun_jpeg_init_source; text: .text%consume_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; text: .text%read_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%sun_jpeg_fill_input_buffer; -text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; -text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; +# text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%emit_message: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jerror.o; -text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_interesting_appn: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%examine_app0: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%examine_app0: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%skip_variable: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%sun_jpeg_skip_input_data; -text: .text%examine_app14: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%examine_app14: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_dqt: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jAlcQTable; text: .text%get_sof: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_dht: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jAlcHTable; text: .text%get_sos: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%initial_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; +# text: .text%initial_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; text: .text%jDivRound; -text: .text%default_decompress_parms: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapimin.o; +# text: .text%default_decompress_parms: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapimin.o; text: .text%jHasMultScn; text: .text%jStrtDecompress; text: .text%jIDMaster; -text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%jCalcDimensions; -text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; -text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%jIDColor; -text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; +# text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; text: .text%jIUpsampler; text: .text%jRound; text: .text%alloc_sarray: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o; @@ -70,16 +70,16 @@ text: .text%jIHDecoder; text: .text%jIDCoefC; text: .text%jIDMainC; -text: .text%alloc_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%alloc_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%realize_virt_arrays: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o; text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; -text: .text%per_scan_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; -text: .text%latch_quant_tables: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; +# text: .text%per_scan_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; +# text: .text%latch_quant_tables: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; text: .text%start_pass_huff_decoder: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; text: .text%jMkDDerived; text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; -text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; -text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapistd.o; +# text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; +# text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapistd.o; text: .text%prepare_for_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%start_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jddctmgr.o; text: .text%start_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; @@ -87,7 +87,7 @@ text: .text%start_pass_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%start_pass_dpost: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdpostct.o; text: .text%start_pass_main: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; -text: .text%make_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%make_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%jReadScanlines; text: .text%process_data_context_main: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%decompress_onepass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; @@ -100,11 +100,11 @@ text: .text%fullsize_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%h2v2_fancy_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%ycc_rgb_convert: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; -text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; -text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; +# text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; text: .text%read_restart_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%finish_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; -text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%jFinDecompress; text: .text%finish_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%sun_jpeg_term_source;
--- a/jdk/make/sun/jpeg/reorder-sparc Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/make/sun/jpeg/reorder-sparc Sun Mar 06 20:32:49 2011 -0800 @@ -30,10 +30,10 @@ text: .text%sun_jpeg_init_source; text: .text%consume_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; text: .text%read_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%sun_jpeg_fill_input_buffer; text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o; -text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%emit_message: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jerror.o; text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_interesting_appn: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; @@ -44,7 +44,7 @@ text: .text%get_dqt: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jAlcQTable; text: .text%get_sof: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; -text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; +# text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%get_dht: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%jAlcHTable; text: .text%get_sos: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; @@ -56,10 +56,10 @@ text: .text%jIDMaster; text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%jCalcDimensions; -text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; -text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; +# text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%jIDColor; -text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; +# text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; text: .text%jIUpsampler; text: .text%jRound; text: .text%alloc_sarray: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o; @@ -78,7 +78,7 @@ text: .text%start_pass_huff_decoder: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; text: .text%jMkDDerived; text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; -text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; +# text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o; text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapistd.o; text: .text%prepare_for_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%start_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jddctmgr.o; @@ -100,11 +100,11 @@ text: .text%fullsize_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%h2v2_fancy_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o; text: .text%ycc_rgb_convert: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o; -text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; -text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; +# text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +#text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o; text: .text%read_restart_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o; text: .text%finish_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o; -text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; +# text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o; text: .text%jFinDecompress; text: .text%finish_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o; text: .text%sun_jpeg_term_source;
--- a/jdk/make/sun/jpeg/reorder-sparcv9 Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/make/sun/jpeg/reorder-sparcv9 Sun Mar 06 20:32:49 2011 -0800 @@ -30,10 +30,10 @@ text: .text%sun_jpeg_init_source; text: .text%consume_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdinput.o; text: .text%read_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; -text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; +# text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%sun_jpeg_fill_input_buffer; text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jpegdecoder.o; -text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; +# text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%emit_message: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jerror.o; text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%get_interesting_appn: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; @@ -44,7 +44,7 @@ text: .text%get_dqt: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%jAlcQTable; text: .text%get_sof: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; -text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; +# text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%get_dht: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%jAlcHTable; text: .text%get_sos: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; @@ -56,10 +56,10 @@ text: .text%jIDMaster; text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; text: .text%jCalcDimensions; -text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; -text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; +# text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; +# text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; text: .text%jIDColor; -text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcolor.o; +# text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcolor.o; text: .text%jIUpsampler; text: .text%jRound; text: .text%alloc_sarray: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jmemmgr.o; @@ -78,7 +78,7 @@ text: .text%start_pass_huff_decoder: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdhuff.o; text: .text%jMkDDerived; text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcoefct.o; -text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcoefct.o; +# text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcoefct.o; text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdapistd.o; text: .text%prepare_for_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; text: .text%start_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jddctmgr.o; @@ -100,11 +100,11 @@ text: .text%fullsize_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdsample.o; text: .text%h2v2_fancy_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdsample.o; text: .text%ycc_rgb_convert: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcolor.o; -text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o; +# text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o; text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdhuff.o; text: .text%read_restart_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o; text: .text%finish_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdinput.o; -text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o; +# text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o; text: .text%jFinDecompress; text: .text%finish_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o; text: .text%sun_jpeg_term_source;
--- a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.FormatConversionProvider Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.FormatConversionProvider Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ # Providers for FormatConversion +com.sun.media.sound.AudioFloatFormatConverter com.sun.media.sound.UlawCodec com.sun.media.sound.AlawCodec com.sun.media.sound.PCMtoPCMCodec -com.sun.media.sound.AudioFloatFormatConverter
--- a/jdk/src/share/classes/java/dyn/CallSite.java Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/src/share/classes/java/dyn/CallSite.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,7 +78,7 @@ } private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) { // ignore caller and name, but match the type: - return new ConstantCallSite(MethodHandles.collectArguments(printArgs, type)); + return new ConstantCallSite(printArgs.asType(type)); } </pre></blockquote> * @author John Rose, JSR 292 EG @@ -86,6 +86,7 @@ abstract public class CallSite { private static final Access IMPL_TOKEN = Access.getToken(); + static { MethodHandleImpl.initStatics(); } // Fields used only by the JVM. Do not use or change. private MemberName vmmethod; // supplied by the JVM (ref. to calling method) @@ -125,8 +126,8 @@ } /** - * Report the type of this call site's target. - * Although targets may change, the call site's type can never change. + * Returns the type of this call site's target. + * Although targets may change, any call site's type is permanent, and can never change to an unequal type. * The {@code setTarget} method enforces this invariant by refusing any new target that does * not have the previous target's type. * @return the type of the current target, which is also the type of any future target @@ -154,73 +155,40 @@ } /** - * Report the current linkage state of the call site, a value which may change over time. - * <p> - * If a {@code CallSite} object is returned - * from the bootstrap method of the {@code invokedynamic} instruction, - * the {@code CallSite} is permanently bound to that instruction. - * When the {@code invokedynamic} instruction is executed, the target method - * of its associated call site object is invoked directly. - * It is as if the instruction calls {@code getTarget} and then - * calls {@link MethodHandle#invokeExact invokeExact} on the result. - * <p> - * Unless specified differently by a subclass, - * the interactions of {@code getTarget} with memory are the same - * as of a read from an ordinary variable, such as an array element or a - * non-volatile, non-final field. - * <p> - * In particular, the current thread may choose to reuse the result - * of a previous read of the target from memory, and may fail to see - * a recent update to the target by another thread. - * <p> - * In a {@linkplain ConstantCallSite constant call site}, the {@code getTarget} method behaves - * like a read from a {@code final} field of the {@code CallSite}. - * <p> - * In a {@linkplain VolatileCallSite volatile call site}, the {@code getTarget} method behaves - * like a read from a {@code volatile} field of the {@code CallSite}. - * <p> - * This method may not be overridden by application code. + * Returns the target method of the call site, according to the + * behavior defined by this call site's specific class. + * The immediate subclasses of {@code CallSite} document the + * class-specific behaviors of this method. + * * @return the current linkage state of the call site, its target method handle * @see ConstantCallSite * @see VolatileCallSite * @see #setTarget + * @see ConstantCallSite#getTarget + * @see MutableCallSite#getTarget + * @see VolatileCallSite#getTarget */ - public final MethodHandle getTarget() { - return getTarget0(); - } + public abstract MethodHandle getTarget(); /** - * Privileged implementations can override this to force final or volatile semantics on getTarget. - */ - /*package-private*/ - MethodHandle getTarget0() { - return target; - } - - /** - * Set the target method of this call site. + * Updates the target method of this call site, according to the + * behavior defined by this call site's specific class. + * The immediate subclasses of {@code CallSite} document the + * class-specific behaviors of this method. * <p> - * Unless a subclass of CallSite documents otherwise, - * the interactions of {@code setTarget} with memory are the same - * as of a write to an ordinary variable, such as an array element or a - * non-volatile, non-final field. - * <p> - * In particular, unrelated threads may fail to see the updated target - * until they perform a read from memory. - * Stronger guarantees can be created by putting appropriate operations - * into the bootstrap method and/or the target methods used - * at any given call site. + * The type of the new target must be {@linkplain MethodType#equals equal to} + * the type of the old target. + * * @param newTarget the new target * @throws NullPointerException if the proposed new target is null * @throws WrongMethodTypeException if the proposed new target * has a method type that differs from the previous target - * @throws UnsupportedOperationException if the call site is - * in fact a {@link ConstantCallSite} + * @see CallSite#getTarget + * @see ConstantCallSite#setTarget + * @see MutableCallSite#setTarget + * @see VolatileCallSite#setTarget */ - public void setTarget(MethodHandle newTarget) { - checkTargetChange(this.target, newTarget); - setTargetNormal(newTarget); - } + public abstract void setTarget(MethodHandle newTarget); void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) { MethodType oldType = oldTarget.type(); @@ -236,31 +204,31 @@ /** * Produce a method handle equivalent to an invokedynamic instruction * which has been linked to this call site. - * <p>If this call site is a {@linkplain ConstantCallSite constant call site}, - * this method simply returns the call site's target, since that will never change. - * <p>Otherwise, this method is equivalent to the following code: - * <p><blockquote><pre> + * <p> + * This method is equivalent to the following code: + * <blockquote><pre> * MethodHandle getTarget, invoker, result; - * getTarget = MethodHandles.lookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class)); + * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class)); * invoker = MethodHandles.exactInvoker(this.type()); * result = MethodHandles.foldArguments(invoker, getTarget) * </pre></blockquote> + * * @return a method handle which always invokes this call site's current target */ - public final MethodHandle dynamicInvoker() { - if (this instanceof ConstantCallSite) { - return getTarget0(); // will not change dynamically - } + public abstract MethodHandle dynamicInvoker(); + + /*non-public*/ MethodHandle makeDynamicInvoker() { MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this); MethodHandle invoker = MethodHandles.exactInvoker(this.type()); return MethodHandles.foldArguments(invoker, getTarget); } + private static final MethodHandle GET_TARGET; static { try { GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP. findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); - } catch (NoAccessException ignore) { + } catch (ReflectiveOperationException ignore) { throw new InternalError(); } }
--- a/jdk/src/share/classes/java/dyn/ClassValue.java Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/src/share/classes/java/dyn/ClassValue.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,10 +31,14 @@ import java.lang.reflect.UndeclaredThrowableException; /** - * Lazily associate a computed value with (potentially) every class. + * Lazily associate a computed value with (potentially) every type. + * For example, if a dynamic language needs to construct a message dispatch + * table for each class encountered at a message send call site, + * it can use a {@code ClassValue} to cache information needed to + * perform the message send quickly, for each class encountered. * @author John Rose, JSR 292 EG */ -public class ClassValue<T> { +public abstract class ClassValue<T> { /** * Compute the given class's derived value for this {@code ClassValue}. * <p> @@ -45,61 +49,41 @@ * but it may be invoked again if there has been a call to * {@link #remove remove}. * <p> - * If there is no override from a subclass, this method returns - * the result of applying the {@code ClassValue}'s {@code computeValue} - * method handle, which was supplied at construction time. + * If this method throws an exception, the corresponding call to {@code get} + * will terminate abnormally with that exception, and no class value will be recorded. * + * @param type the type whose class value must be computed * @return the newly computed value associated with this {@code ClassValue}, for the given class or interface - * @throws UndeclaredThrowableException if the {@code computeValue} method handle invocation throws something other than a {@code RuntimeException} or {@code Error} - * @throws UnsupportedOperationException if the {@code computeValue} method handle is null (subclasses must override) + * @see #get + * @see #remove */ - protected T computeValue(Class<?> type) { - if (computeValue == null) - return null; - try { - return (T) (Object) computeValue.invokeGeneric(type); - } catch (Throwable ex) { - if (ex instanceof Error) throw (Error) ex; - if (ex instanceof RuntimeException) throw (RuntimeException) ex; - throw new UndeclaredThrowableException(ex); - } - } - - private final MethodHandle computeValue; - - /** - * Creates a new class value. - * Subclasses which use this constructor must override - * the {@link #computeValue computeValue} method, - * since the default {@code computeValue} method requires a method handle, - * which this constructor does not provide. - */ - protected ClassValue() { - this.computeValue = null; - } - - /** - * Creates a new class value, whose {@link #computeValue computeValue} method - * will return the result of {@code computeValue.invokeGeneric(type)}. - * @throws NullPointerException if the method handle parameter is null - */ - public ClassValue(MethodHandle computeValue) { - computeValue.getClass(); // trigger NPE if null - this.computeValue = computeValue; - } + protected abstract T computeValue(Class<?> type); /** * Returns the value for the given class. * If no value has yet been computed, it is obtained by - * by an invocation of the {@link #computeValue computeValue} method. + * an invocation of the {@link #computeValue computeValue} method. * <p> * The actual installation of the value on the class * is performed atomically. - * At that point, if racing threads have + * At that point, if several racing threads have * computed values, one is chosen, and returned to * all the racing threads. + * <p> + * The {@code type} parameter is typically a class, but it may be any type, + * such as an interface, a primitive type (like {@code int.class}), or {@code void.class}. + * <p> + * In the absence of {@code remove} calls, a class value has a simple + * state diagram: uninitialized and initialized. + * When {@code remove} calls are made, + * the rules for value observation are more complex. + * See the documentation for {@link #remove remove} for more information. * + * @param type the type whose class value must be computed or retrieved * @return the current value associated with this {@code ClassValue}, for the given class or interface + * @throws NullPointerException if the argument is null + * @see #remove + * @see #computeValue */ public T get(Class<?> type) { ClassValueMap map = getMap(type); @@ -119,12 +103,51 @@ * This may result in an additional invocation of the * {@code computeValue computeValue} method for the given class. * <p> - * If racing threads perform a combination of {@code get} and {@code remove} calls, - * the calls are serialized. - * A value produced by a call to {@code computeValue} will be discarded, if - * the corresponding {@code get} call was followed by a {@code remove} call - * before the {@code computeValue} could complete. - * In such a case, the {@code get} call will re-invoke {@code computeValue}. + * In order to explain the interaction between {@code get} and {@code remove} calls, + * we must model the state transitions of a class value to take into account + * the alternation between uninitialized and initialized states. + * To do this, number these states sequentially from zero, and note that + * uninitialized (or removed) states are numbered with even numbers, + * while initialized (or re-initialized) states have odd numbers. + * <p> + * When a thread {@code T} removes a class value in state {@code 2N}, + * nothing happens, since the class value is already uninitialized. + * Otherwise, the state is advanced atomically to {@code 2N+1}. + * <p> + * When a thread {@code T} queries a class value in state {@code 2N}, + * the thread first attempts to initialize the class value to state {@code 2N+1} + * by invoking {@code computeValue} and installing the resulting value. + * <p> + * When {@code T} attempts to install the newly computed value, + * if the state is still at {@code 2N}, the class value will be initialized + * with the computed value, advancing it to state {@code 2N+1}. + * <p> + * Otherwise, whether the new state is even or odd, + * {@code T} will discard the newly computed value + * and retry the {@code get} operation. + * <p> + * Discarding and retrying is an important proviso, + * since otherwise {@code T} could potentially install + * a disastrously stale value. For example: + * <ul> + * <li>{@code T} calls {@code CV.get(C)} and sees state {@code 2N} + * <li>{@code T} quickly computes a time-dependent value {@code V0} and gets ready to install it + * <li>{@code T} is hit by an unlucky paging or scheduling event, and goes to sleep for a long time + * <li>...meanwhile, {@code T2} also calls {@code CV.get(C)} and sees state {@code 2N} + * <li>{@code T2} quickly computes a similar time-dependent value {@code V1} and installs it on {@code CV.get(C)} + * <li>{@code T2} (or a third thread) then calls {@code CV.remove(C)}, undoing {@code T2}'s work + * <li> the previous actions of {@code T2} are repeated several times + * <li> also, the relevant computed values change over time: {@code V1}, {@code V2}, ... + * <li>...meanwhile, {@code T} wakes up and attempts to install {@code V0}; <em>this must fail</em> + * </ul> + * We can assume in the above scenario that {@code CV.computeValue} uses locks to properly + * observe the time-dependent states as it computes {@code V1}, etc. + * This does not remove the threat of a stale value, since there is a window of time + * between the return of {@code computeValue} in {@code T} and the installation + * of the the new value. No user synchronization is possible during this time. + * + * @param type the type whose class value must be removed + * @throws NullPointerException if the argument is null */ public void remove(Class<?> type) { ClassValueMap map = getMap(type); @@ -137,9 +160,9 @@ /// Implementation... - /** The hash code for this type is based on the identity of the object, - * and is well-dispersed for power-of-two tables. - */ + // The hash code for this type is based on the identity of the object, + // and is well-dispersed for power-of-two tables. + /** @deprecated This override, which is implementation-specific, will be removed for PFD. */ public final int hashCode() { return hashCode; } private final int hashCode = HASH_CODES.getAndAdd(0x61c88647); private static final AtomicInteger HASH_CODES = new AtomicInteger();
--- a/jdk/src/share/classes/java/dyn/ConstantCallSite.java Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/src/share/classes/java/dyn/ConstantCallSite.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,16 +32,46 @@ * @author John Rose, JSR 292 EG */ public class ConstantCallSite extends CallSite { - /** Create a call site with a permanent target. + /** + * Creates a call site with a permanent target. + * @param target the target to be permanently associated with this call site * @throws NullPointerException if the proposed target is null */ public ConstantCallSite(MethodHandle target) { super(target); } + /** - * Throw an {@link UnsupportedOperationException}, because this kind of call site cannot change its target. + * Returns the target method of the call site, which behaves + * like a {@code final} field of the {@code ConstantCallSite}. + * That is, the the target is always the original value passed + * to the constructor call which created this instance. + * + * @return the immutable linkage state of this call site, a constant method handle + * @throws UnsupportedOperationException because this kind of call site cannot change its target + */ + @Override public final MethodHandle getTarget() { + return target; + } + + /** + * Always throws an {@link UnsupportedOperationException}. + * This kind of call site cannot change its target. + * @param ignore a new target proposed for the call site, which is ignored + * @throws UnsupportedOperationException because this kind of call site cannot change its target */ @Override public final void setTarget(MethodHandle ignore) { throw new UnsupportedOperationException("ConstantCallSite"); } + + /** + * Returns this call site's permanent target. + * Since that target will never change, this is a correct implementation + * of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}. + * @return the immutable linkage state of this call site, a constant method handle + */ + @Override + public final MethodHandle dynamicInvoker() { + return getTarget(); + } }
--- a/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java Sun Mar 06 20:32:49 2011 -0800 @@ -31,8 +31,8 @@ * {@linkplain BootstrapMethod bootstrap method}, * or the bootstrap method has * failed to provide a - * {@linkplain CallSite} call site with a non-null {@linkplain MethodHandle target} - * of the correct {@linkplain MethodType method type}. + * {@linkplain CallSite call site} with a {@linkplain CallSite#getTarget target} + * of the correct {@linkplain MethodHandle#type method type}. * * @author John Rose, JSR 292 EG * @since 1.7
--- a/jdk/src/share/classes/java/dyn/Linkage.java Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/src/share/classes/java/dyn/Linkage.java Sun Mar 06 20:32:49 2011 -0800 @@ -88,7 +88,7 @@ MethodHandle bootstrapMethod; try { bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex); } MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod); @@ -101,8 +101,9 @@ /** * <em>METHOD WILL BE REMOVED FOR PFD:</em> * Invalidate all <code>invokedynamic</code> call sites everywhere. - * @deprecated Use {@linkplain CallSite#setTarget call site target setting} - * and {@link VolatileCallSite#invalidateAll call site invalidation} instead. + * @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting}, + * {@link MutableCallSite#syncAll call site update pushing}, + * and {@link SwitchPoint#guardWithTest target switching} instead. */ public static Object invalidateAll() { @@ -113,8 +114,9 @@ * <em>METHOD WILL BE REMOVED FOR PFD:</em> * Invalidate all {@code invokedynamic} call sites in the bytecodes * of any methods of the given class. - * @deprecated Use {@linkplain CallSite#setTarget call site target setting} - * and {@link VolatileCallSite#invalidateAll call site invalidation} instead. + * @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting}, + * {@link MutableCallSite#syncAll call site update pushing}, + * and {@link SwitchPoint#guardWithTest target switching} instead. */ public static Object invalidateCallerClass(Class<?> callerClass) {
--- a/jdk/src/share/classes/java/dyn/MethodHandle.java Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/src/share/classes/java/dyn/MethodHandle.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility /** - * A method handle is a typed, directly executable reference to a method, + * A method handle is a typed, directly executable reference to an underlying method, * constructor, field, or similar low-level operation, with optional * transformations of arguments or return values. * These transformations are quite general, and include such patterns as @@ -48,99 +48,182 @@ * will be removed before the Proposed Final Draft. * Also, the final version will not include any public or * protected constructors.</em> - * <p> - * Method handles are strongly typed according to signature. - * They are not distinguished by method name or enclosing class. - * A method handle must be invoked under a signature which matches - * the method handle's own {@linkplain MethodType method type}. + * + * <h3>Method handle contents</h3> + * Method handles are dynamically and strongly typed according to type descriptor. + * They are not distinguished by the name or defining class of their underlying methods. + * A method handle must be invoked using type descriptor which matches + * the method handle's own {@linkplain #type method type}. * <p> * Every method handle reports its type via the {@link #type type} accessor. - * The structure of this type is a series of classes, one of which is + * This type descriptor is a {@link java.dyn.MethodType MethodType} object, + * whose structure is a series of classes, one of which is * the return type of the method (or {@code void.class} if none). * <p> - * Every method handle appears as an object containing a method named - * {@link #invokeExact invokeExact}, whose signature exactly matches - * the method handle's type. - * A Java method call expression, which compiles to an - * {@code invokevirtual} instruction, - * can invoke this method from Java source code. + * A method handle's type controls the types of invocations it accepts, + * and the kinds of transformations that apply to it. + * <p> + * A method handle contains a pair of special invoker methods + * called {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}. + * Both invoker methods provide direct access to the method handle's + * underlying method, constructor, field, or other operation, + * as modified by transformations of arguments and return values. + * Both invokers accept calls which exactly match the method handle's own type. + * The {@code invokeGeneric} invoker also accepts a range of other call types. + * <p> + * Method handles are immutable and have no visible state. + * Of course, they can be bound to underlying methods or data which exhibit state. + * With respect to the Java Memory Model, any method handle will behave + * as if all of its (internal) fields are final variables. This means that any method + * handle made visible to the application will always be fully formed. + * This is true even if the method handle is published through a shared + * variable in a data race. + * <p> + * Method handles cannot be subclassed by the user. + * Implementations may (or may not) create internal subclasses of {@code MethodHandle} + * which may be visible via the {@link java.lang.Object#getClass Object.getClass} + * operation. The programmer should not draw conclusions about a method handle + * from its specific class, as the method handle class hierarchy (if any) + * may change from time to time or across implementations from different vendors. + * + * <h3>Method handle compilation</h3> + * A Java method call expression naming {@code invokeExact} or {@code invokeGeneric} + * can invoke a method handle from Java source code. + * From the viewpoint of source code, these methods can take any arguments + * and their result can be cast to any return type. + * Formally this is accomplished by giving the invoker methods + * {@code Object} return types and variable-arity {@code Object} arguments, + * but they have an additional quality called <em>signature polymorphism</em> + * which connects this freedom of invocation directly to the JVM execution stack. * <p> - * Every call to a method handle specifies an intended method type, - * which must exactly match the type of the method handle. - * (The type is specified in the {@code invokevirtual} instruction, - * via a {@code CONSTANT_NameAndType} constant pool entry.) - * The call looks within the receiver object for a method - * named {@code invokeExact} of the intended method type. - * The call fails with a {@link WrongMethodTypeException} - * if the method does not exist, even if there is an {@code invokeExact} - * method of a closely similar signature. - * As with other kinds - * of methods in the JVM, signature matching during method linkage - * is exact, and does not allow for language-level implicit conversions - * such as {@code String} to {@code Object} or {@code short} to {@code int}. + * As is usual with virtual methods, source-level calls to {@code invokeExact} + * and {@code invokeGeneric} compile to an {@code invokevirtual} instruction. + * More unusually, the compiler must record the actual argument types, + * and may not perform method invocation conversions on the arguments. + * Instead, it must push them on the stack according to their own unconverted types. + * The method handle object itself is pushed on the stack before the arguments. + * The compiler then calls the method handle with a type descriptor which + * describes the argument and return types. + * <p> + * To issue a complete type descriptor, the compiler must also determine + * the return type. This is based on a cast on the method invocation expression, + * if there is one, or else {@code Object} if the invocation is an expression + * or else {@code void} if the invocation is a statement. + * The cast may be to a primitive type (but not {@code void}). * <p> - * Each individual method handle also contains a method named - * {@link #invokeGeneric invokeGeneric}, whose type is the same - * as {@code invokeExact}, and is therefore also reported by - * the {@link #type type} accessor. + * As a corner case, an uncasted {@code null} argument is given + * a type descriptor of {@code java.lang.Void}. + * The ambiguity with the type {@code Void} is harmless, since there are no references of type + * {@code Void} except the null reference. + * + * <h3>Method handle invocation</h3> + * The first time a {@code invokevirtual} instruction is executed + * it is linked, by symbolically resolving the names in the instruction + * and verifying that the method call is statically legal. + * This is true of calls to {@code invokeExact} and {@code invokeGeneric}. + * In this case, the type descriptor emitted by the compiler is checked for + * correct syntax and names it contains are resolved. + * Thus, an {@code invokevirtual} instruction which invokes + * a method handle will always link, as long + * as the type descriptor is syntactically well-formed + * and the types exist. + * <p> + * When the {@code invokevirtual} is executed after linking, + * the receiving method handle's type is first checked by the JVM + * to ensure that it matches the descriptor. + * If the type match fails, it means that the method which the + * caller is invoking is not present on the individual + * method handle being invoked. + * <p> + * In the case of {@code invokeExact}, the type descriptor of the invocation + * (after resolving symbolic type names) must exactly match the method type + * of the receiving method handle. + * In the case of {@code invokeGeneric}, the resolved type descriptor + * must be a valid argument to the receiver's {@link #asType asType} method. + * Thus, {@code invokeGeneric} is more permissive than {@code invokeExact}. + * <p> + * After type matching, a call to {@code invokeExact} directly + * and immediately invoke the method handle's underlying method + * (or other behavior, as the case may be). + * <p> * A call to {@code invokeGeneric} works the same as a call to - * {@code invokeExact}, if the signature specified by the caller + * {@code invokeExact}, if the type descriptor specified by the caller * exactly matches the method handle's own type. * If there is a type mismatch, {@code invokeGeneric} attempts - * to adjust the type of the target method handle - * (as if by a call to {@link #asType asType}) - * to obtain an exactly invokable target. + * to adjust the type of the receiving method handle, + * as if by a call to {@link #asType asType}, + * to obtain an exactly invokable method handle {@code M2}. * This allows a more powerful negotiation of method type * between caller and callee. * <p> - * A method handle is an unrestricted capability to call a method. - * A method handle can be formed on a non-public method by a class - * that has access to that method; the resulting handle can be used - * in any place by any caller who receives a reference to it. Thus, access - * checking is performed when the method handle is created, not - * (as in reflection) every time it is called. Handles to non-public - * methods, or in non-public classes, should generally be kept secret. + * (Note: The adjusted method handle {@code M2} is not directly observable, + * and implementations are therefore not required to materialize it.) + * + * <h3>Invocation checking</h3> + * In typical programs, method handle type matching will usually succeed. + * But if a match fails, the JVM will throw a {@link WrongMethodTypeException}, + * either directly (in the case of {@code invokeExact}) or indirectly as if + * by a failed call to {@code asType} (in the case of {@code invokeGeneric}). + * <p> + * Thus, a method type mismatch which might show up as a linkage error + * in a statically typed program can show up as + * a dynamic {@code WrongMethodTypeException} + * in a program which uses method handles. + * <p> + * Because method types contain "live" {@code Class} objects, + * method type matching takes into account both types names and class loaders. + * Thus, even if a method handle {@code M} is created in one + * class loader {@code L1} and used in another {@code L2}, + * method handle calls are type-safe, because the caller's type + * descriptor, as resolved in {@code L2}, + * is matched against the original callee method's type descriptor, + * as resolved in {@code L1}. + * The resolution in {@code L1} happens when {@code M} is created + * and its type is assigned, while the resolution in {@code L2} happens + * when the {@code invokevirtual} instruction is linked. + * <p> + * Apart from the checking of type descriptors, + * a method handle's capability to call its underlying method is unrestricted. + * If a method handle is formed on a non-public method by a class + * that has access to that method, the resulting handle can be used + * in any place by any caller who receives a reference to it. + * <p> + * Unlike with the Core Reflection API, where access is checked every time + * a reflective method is invoked, + * method handle access checking is performed + * <a href="MethodHandles.Lookup.html#access">when the method handle is created</a>. + * In the case of {@code ldc} (see below), access checking is performed as part of linking + * the constant pool entry underlying the constant method handle. + * <p> + * Thus, handles to non-public methods, or to methods in non-public classes, + * should generally be kept secret. * They should not be passed to untrusted code unless their use from * the untrusted code would be harmless. - * <p> - * Bytecode in the JVM can directly call a method handle's - * {@code invokeExact} method from an {@code invokevirtual} instruction. - * The receiver class type must be {@code MethodHandle} and the method name - * must be {@code invokeExact}. The signature of the invocation - * (after resolving symbolic type names) must exactly match the method type - * of the target method. - * Similarly, bytecode can directly call a method handle's {@code invokeGeneric} - * method. The signature of the invocation (after resolving symbolic type names) - * must either exactly match the method type or be a valid argument to - * the target's {@link #asType asType} method. + * + * <h3>Method handle creation</h3> + * Java code can create a method handle that directly accesses + * any method, constructor, or field that is accessible to that code. + * This is done via a reflective, capability-based API called + * {@link java.dyn.MethodHandles.Lookup MethodHandles.Lookup} + * For example, a static method handle can be obtained + * from {@link java.dyn.MethodHandles.Lookup#findStatic Lookup.findStatic}. + * There are also conversion methods from Core Reflection API objects, + * such as {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}. * <p> - * Every {@code invokeExact} and {@code invokeGeneric} method always - * throws {@link java.lang.Throwable Throwable}, - * which is to say that there is no static restriction on what a method handle - * can throw. Since the JVM does not distinguish between checked - * and unchecked exceptions (other than by their class, of course), - * there is no particular effect on bytecode shape from ascribing - * checked exceptions to method handle invocations. But in Java source - * code, methods which perform method handle calls must either explicitly - * throw {@code java.lang.Throwable Throwable}, or else must catch all - * throwables locally, rethrowing only those which are legal in the context, - * and wrapping ones which are illegal. - * <p> - * Bytecode in the JVM can directly obtain a method handle - * for any accessible method from a {@code ldc} instruction - * which refers to a {@code CONSTANT_MethodHandle} constant pool entry. - * (Each such entry refers directly to a {@code CONSTANT_Methodref}, + * Like classes and strings, method handles that correspond to accessible + * fields, methods, and constructors can also be represented directly + * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes. + * A new type of constant pool entry, {@code CONSTANT_MethodHandle}, + * refers directly to an associated {@code CONSTANT_Methodref}, * {@code CONSTANT_InterfaceMethodref}, or {@code CONSTANT_Fieldref} * constant pool entry. - * For more details, see the <a href="package-summary.html#mhcon">package summary</a>.) + * (For more details on method handle constants, + * see the <a href="package-summary.html#mhcon">package summary</a>.) * <p> - * Java code can also use a reflective API called - * {@link java.dyn.MethodHandles.Lookup MethodHandles.Lookup} - * for creating and calling method handles. - * For example, a static method handle can be obtained - * from {@link java.dyn.MethodHandles.Lookup#findStatic Lookup.findStatic}. - * There are also bridge methods from Core Reflection API objects, - * such as {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.ureflect}. + * Method handles produced by lookups or constant loads from methods or + * constructors with the variable arity modifier bit ({@code 0x0080}) + * have a corresponding variable arity, as if they were defined with + * the help of {@link #asVarargsCollector asVarargsCollector}. * <p> * A method reference may refer either to a static or non-static method. * In the non-static case, the method handle type includes an explicit @@ -153,61 +236,191 @@ * When a method handle to a virtual method is invoked, the method is * always looked up in the receiver (that is, the first argument). * <p> - * A non-virtual method handles to a specific virtual method implementation + * A non-virtual method handle to a specific virtual method implementation * can also be created. These do not perform virtual lookup based on * receiver type. Such a method handle simulates the effect of * an {@code invokespecial} instruction to the same method. - * <p> + * + * <h3>Usage examples</h3> * Here are some examples of usage: * <p><blockquote><pre> Object x, y; String s; int i; MethodType mt; MethodHandle mh; MethodHandles.Lookup lookup = MethodHandles.lookup(); -// mt is {(char,char) => String} +// mt is (char,char)String mt = MethodType.methodType(String.class, char.class, char.class); mh = lookup.findVirtual(String.class, "replace", mt); -// (Ljava/lang/String;CC)Ljava/lang/String; s = (String) mh.invokeExact("daddy",'d','n'); +// invokeExact(Ljava/lang/String;CC)Ljava/lang/String; assert(s.equals("nanny")); // weakly typed invocation (using MHs.invoke) s = (String) mh.invokeWithArguments("sappy", 'p', 'v'); assert(s.equals("savvy")); -// mt is {Object[] => List} +// mt is (Object[])List mt = MethodType.methodType(java.util.List.class, Object[].class); mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); -// mt is {(Object,Object,Object) => Object} +assert(mh.isVarargsCollector()); +x = mh.invokeGeneric("one", "two"); +// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; +assert(x.equals(java.util.Arrays.asList("one","two"))); +// mt is (Object,Object,Object)Object mt = MethodType.genericMethodType(3); -mh = MethodHandles.collectArguments(mh, mt); -// mt is {(Object,Object,Object) => Object} -// (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +mh = mh.asType(mt); x = mh.invokeExact((Object)1, (Object)2, (Object)3); +// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; assert(x.equals(java.util.Arrays.asList(1,2,3))); // mt is { => int} mt = MethodType.methodType(int.class); mh = lookup.findVirtual(java.util.List.class, "size", mt); -// (Ljava/util/List;)I i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3)); +// invokeExact(Ljava/util/List;)I assert(i == 3); mt = MethodType.methodType(void.class, String.class); mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt); mh.invokeExact(System.out, "Hello, world."); -// (Ljava/io/PrintStream;Ljava/lang/String;)V +// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V * </pre></blockquote> - * Each of the above calls generates a single invokevirtual instruction - * with the name {@code invoke} and the type descriptors indicated in the comments. - * The argument types are taken directly from the actual arguments, - * while the return type is taken from the cast immediately applied to the call. - * This cast may be to a primitive. - * If it is missing, the type defaults to {@code Object} if the call - * occurs in a context which uses the return value. - * If the call occurs as a statement, a cast is impossible, - * and there is no return type; the call is {@code void}. + * Each of the above calls to {@code invokeExact} or {@code invokeGeneric} + * generates a single invokevirtual instruction with + * the type descriptor indicated in the following comment. + * + * <h3>Exceptions</h3> + * The methods {@code invokeExact} and {@code invokeGeneric} are declared + * to throw {@link java.lang.Throwable Throwable}, + * which is to say that there is no static restriction on what a method handle + * can throw. Since the JVM does not distinguish between checked + * and unchecked exceptions (other than by their class, of course), + * there is no particular effect on bytecode shape from ascribing + * checked exceptions to method handle invocations. But in Java source + * code, methods which perform method handle calls must either explicitly + * throw {@code java.lang.Throwable Throwable}, or else must catch all + * throwables locally, rethrowing only those which are legal in the context, + * and wrapping ones which are illegal. + * + * <h3><a name="sigpoly"></a>Signature polymorphism</h3> + * The unusual compilation and linkage behavior of + * {@code invokeExact} and {@code invokeGeneric} + * is referenced by the term <em>signature polymorphism</em>. + * A signature polymorphic method is one which can operate with + * any of a wide range of call signatures and return types. + * In order to make this work, both the Java compiler and the JVM must + * give special treatment to signature polymorphic methods. + * <p> + * In source code, a call to a signature polymorphic method will + * compile, regardless of the requested type descriptor. + * As usual, the Java compiler emits an {@code invokevirtual} + * instruction with the given type descriptor against the named method. + * The unusual part is that the type descriptor is derived from + * the actual argument and return types, not from the method declaration. + * <p> + * When the JVM processes bytecode containing signature polymorphic calls, + * it will successfully link any such call, regardless of its type descriptor. + * (In order to retain type safety, the JVM will guard such calls with suitable + * dynamic type checks, as described elsewhere.) + * <p> + * Bytecode generators, including the compiler back end, are required to emit + * untransformed type descriptors for these methods. + * Tools which determine symbolic linkage are required to accept such + * untransformed descriptors, without reporting linkage errors. + * <p> + * For the sake of tools (but not as a programming API), the signature polymorphic + * methods are marked with a private yet standard annotation, + * {@code @java.dyn.MethodHandle.PolymorphicSignature}. + * The annotation's retention is {@code RUNTIME}, so that all tools can see it. + * + * <h3>Formal rules for processing signature polymorphic methods</h3> + * <p> + * The following methods (and no others) are signature polymorphic: + * <ul> + * <li>{@link java.dyn.MethodHandle#invokeExact MethodHandle.invokeExact} + * <li>{@link java.dyn.MethodHandle#invokeGeneric MethodHandle.invokeGeneric} + * </ul> + * <p> + * A signature polymorphic method will be declared with the following properties: + * <ul> + * <li>It must be native. + * <li>It must take a single varargs parameter of the form {@code Object...}. + * <li>It must produce a return value of type {@code Object}. + * <li>It must be contained within the {@code java.dyn} package. + * </ul> + * Because of these requirements, a signature polymorphic method is able to accept + * any number and type of actual arguments, and can, with a cast, produce a value of any type. + * However, the JVM will treat these declaration features as a documentation convention, + * rather than a description of the actual structure of the methods as executed. * <p> - * <em>A note on generic typing:</em> Method handles do not represent - * their function types in terms of Java parameterized (generic) types, - * because there are three mismatches between function types and parameterized + * When a call to a signature polymorphic method is compiled, the associated linkage information for + * its arguments is not array of {@code Object} (as for other similar varargs methods) + * but rather the erasure of the static types of all the arguments. + * <p> + * In an argument position of a method invocation on a signature polymorphic method, + * a null literal has type {@code java.lang.Void}, unless cast to a reference type. + * (Note: This typing rule allows the null type to have its own encoding in linkage information + * distinct from other types. + * <p> + * The linkage information for the return type is derived from a context-dependent target typing convention. + * The return type for a signature polymorphic method invocation is determined as follows: + * <ul> + * <li>If the method invocation expression is an expression statement, the method is {@code void}. + * <li>Otherwise, if the method invocation expression is the immediate operand of a cast, + * the return type is the erasure of the cast type. + * <li>Otherwise, the return type is the method's nominal return type, {@code Object}. + * </ul> + * (Programmers are encouraged to use explicit casts unless it is clear that a signature polymorphic + * call will be used as a plain {@code Object} expression.) + * <p> + * The linkage information for argument and return types is stored in the descriptor for the + * compiled (bytecode) call site. As for any invocation instruction, the arguments and return value + * will be passed directly on the JVM stack, in accordance with the descriptor, + * and without implicit boxing or unboxing. + * + * <h3>Interoperation between method handles and the Core Reflection API</h3> + * Using factory methods in the {@link java.dyn.MethodHandles.Lookup Lookup} API, + * any class member represented by a Core Reflection API object + * can be converted to a behaviorally equivalent method handle. + * For example, a reflective {@link java.lang.reflect.Method Method} can + * be converted to a method handle using + * {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}. + * The resulting method handles generally provide more direct and efficient + * access to the underlying class members. + * <p> + * As a special case, + * when the Core Reflection API is used to view the signature polymorphic + * methods {@code invokeExact} or {@code invokeGeneric} in this class, + * they appear as single, non-polymorphic native methods. + * Calls to these native methods do not result in method handle invocations. + * Since {@code invokevirtual} instructions can natively + * invoke method handles under any type descriptor, this reflective view conflicts + * with the normal presentation via bytecodes. + * Thus, these two native methods, as viewed by + * {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod}, + * are placeholders only. + * If invoked via {@link java.lang.reflect.Method#invoke Method.invoke}, + * they will throw {@code UnsupportedOperationException}. + * <p> + * In order to obtain an invoker method for a particular type descriptor, + * use {@link java.dyn.MethodHandles#exactInvoker MethodHandles.exactInvoker}, + * or {@link java.dyn.MethodHandles#genericInvoker MethodHandles.genericInvoker}. + * The {@link java.dyn.MethodHandles.Lookup#findVirtual Lookup.findVirtual} + * API is also able to return a method handle + * to call {@code invokeExact} or {@code invokeGeneric}, + * for any specified type descriptor . + * + * <h3>Interoperation between method handles and Java generics</h3> + * A method handle can be obtained on a method, constructor, or field + * which is declared with Java generic types. + * As with the Core Reflection API, the type of the method handle + * will constructed from the erasure of the source-level type. + * When a method handle is invoked, the types of its arguments + * or the return value cast type may be generic types or type instances. + * If this occurs, the compiler will replace those + * types by their erasures when when it constructs the type descriptor + * for the {@code invokevirtual} instruction. + * <p> + * Method handles do not represent + * their function-like types in terms of Java parameterized (generic) types, + * because there are three mismatches between function-like types and parameterized * Java types. - * <ol> + * <ul> * <li>Method types range over all possible arities, * from no arguments to up to 255 of arguments (a limit imposed by the JVM). * Generics are not variadic, and so cannot represent this.</li> @@ -217,29 +430,7 @@ * often generic across a wide range of function types, including * those of multiple arities. It is impossible to represent such * genericity with a Java type parameter.</li> - * </ol> - * Signature polymorphic methods in this class appear to be documented - * as having type parameters for return types and a parameter, but that is - * merely a documentation convention. These type parameters do - * not play a role in type-checking method handle invocations. - * <p> - * Like classes and strings, method handles that correspond to accessible - * fields, methods, and constructors can be represented directly - * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes. - * Loading such a constant causes the component classes of its type to be loaded as necessary. - * <p> - * Method handles cannot be subclassed by the user. - * Implementations may (or may not) create internal subclasses of {@code MethodHandle} - * which may be visible via the {@code java.lang.Object#getClass Object.getClass} - * operation. The programmer should not draw conclusions about a method handle - * from its specific class, as the method handle class hierarchy (if any) - * may change from time to time or across implementations from different vendors. - * <p> - * With respect to the Java Memory Model, any method handle will behave - * as if all of its fields are final variables. This means that any method - * handle made visible to the application will always be fully formed. - * This is true even if the method handle is published through a shared - * variables in a data race. + * </ul> * * @see MethodType * @see MethodHandles @@ -251,15 +442,16 @@ extends MethodHandleImpl { private static Access IMPL_TOKEN = Access.getToken(); + static { MethodHandleImpl.initStatics(); } // interface MethodHandle<R throws X extends Exception,A...> // { MethodType<R throws X,A...> type(); public R invokeExact(A...) throws X; } /** * Internal marker interface which distinguishes (to the Java compiler) - * those methods which are signature polymorphic. + * those methods which are <a href="MethodHandle.html#sigpoly">signature polymorphic</a>. */ - @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.TYPE}) + @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @interface PolymorphicSignature { } @@ -270,7 +462,7 @@ * Every invocation of this method handle via {@code invokeExact} must exactly match this type. * @return the method handle type */ - public final MethodType type() { + public MethodType type() { return type; } @@ -307,40 +499,27 @@ } /** - * Returns a string representation of the method handle, - * starting with the string {@code "MethodHandle"} and - * ending with the string representation of the method handle's type. - * In other words, this method returns a string equal to the value of: - * <blockquote><pre> - * "MethodHandle" + type().toString() - * </pre></blockquote> - * <p> - * Note: Future releases of this API may add further information - * to the string representation. - * Therefore, the present syntax should not be parsed by applications. - * - * @return a string representation of the method handle - */ - @Override - public String toString() { - return MethodHandleImpl.getNameString(IMPL_TOKEN, this); - } - - /** - * Invoke the method handle, allowing any caller signature, but requiring an exact signature match. - * The signature at the call site of {@code invokeExact} must + * Invoke the method handle, allowing any caller type descriptor, but requiring an exact type match. + * The type descriptor at the call site of {@code invokeExact} must * exactly match this method handle's {@link #type type}. * No conversions are allowed on arguments or return values. - * @throws WrongMethodTypeException if the target's type is not identical with the caller's type signature + * <p> + * When this method is observed via the Core Reflection API, + * it will appear as a single native method, taking an object array and returning an object. + * If this native method is invoked directly via + * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI, + * or indirectly via {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}, + * it will throw an {@code UnsupportedOperationException}. + * @throws WrongMethodTypeException if the target's type is not identical with the caller's type descriptor * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call */ public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable; /** - * Invoke the method handle, allowing any caller signature, - * and optionally performing conversions for arguments and return types. + * Invoke the method handle, allowing any caller type descriptor, + * and optionally performing conversions on arguments and return values. * <p> - * If the call site signature exactly matches this method handle's {@link #type type}, + * If the call site type descriptor exactly matches this method handle's {@link #type type}, * the call proceeds as if by {@link #invokeExact invokeExact}. * <p> * Otherwise, the call proceeds as if this method handle were first @@ -353,14 +532,20 @@ * adaptations directly on the caller's arguments, * and call the target method handle according to its own exact type. * <p> - * If the method handle is equipped with a - * {@linkplain #withTypeHandler type handler}, the handler must produce - * an entry point of the call site's exact type. - * Otherwise, the signature at the call site of {@code invokeGeneric} must - * be a valid argument to the standard {@code asType} method. + * The type descriptor at the call site of {@code invokeGeneric} must + * be a valid argument to the receivers {@code asType} method. * In particular, the caller must specify the same argument arity - * as the callee's type. - * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type signature + * as the callee's type, + * if the callee is not a {@linkplain #asVarargsCollector variable arity collector}. + * <p> + * When this method is observed via the Core Reflection API, + * it will appear as a single native method, taking an object array and returning an object. + * If this native method is invoked directly via + * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI, + * or indirectly via {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}, + * it will throw an {@code UnsupportedOperationException}. + * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type descriptor + * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call */ public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable; @@ -400,16 +585,22 @@ * <p> * This call is equivalent to the following code: * <p><blockquote><pre> - * MethodHandle invoker = MethodHandles.varargsInvoker(this.type(), 0); + * MethodHandle invoker = MethodHandles.spreadInvoker(this.type(), 0); * Object result = invoker.invokeExact(this, arguments); * </pre></blockquote> + * <p> + * Unlike the signature polymorphic methods {@code invokeExact} and {@code invokeGeneric}, + * {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI. + * It can therefore be used as a bridge between native or reflective code and method handles. + * * @param arguments the arguments to pass to the target * @return the result returned by the target - * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the arguments + * @throws ClassCastException if an argument cannot be converted by reference casting + * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments * @throws Throwable anything thrown by the target method invocation - * @see MethodHandles#varargsInvoker + * @see MethodHandles#spreadInvoker */ - public final Object invokeWithArguments(Object... arguments) throws Throwable { + public Object invokeWithArguments(Object... arguments) throws Throwable { int argc = arguments == null ? 0 : arguments.length; MethodType type = type(); if (type.parameterCount() != argc) { @@ -417,7 +608,7 @@ return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments); } if (argc <= 10) { - MethodHandle invoker = MethodHandles.invokers(type).genericInvoker(); + MethodHandle invoker = invokers(type).genericInvoker(); switch (argc) { case 0: return invoker.invokeExact(this); case 1: return invoker.invokeExact(this, @@ -456,19 +647,11 @@ } // more than ten arguments get boxed in a varargs list: - MethodHandle invoker = MethodHandles.invokers(type).varargsInvoker(0); + MethodHandle invoker = invokers(type).spreadInvoker(0); return invoker.invokeExact(this, arguments); } /** Equivalent to {@code invokeWithArguments(arguments.toArray())}. */ - public final Object invokeWithArguments(java.util.List<?> arguments) throws Throwable { - return invokeWithArguments(arguments.toArray()); - } - @Deprecated - public final Object invokeVarargs(Object... arguments) throws Throwable { - return invokeWithArguments(arguments); - } - @Deprecated - public final Object invokeVarargs(java.util.List<?> arguments) throws Throwable { + public Object invokeWithArguments(java.util.List<?> arguments) throws Throwable { return invokeWithArguments(arguments.toArray()); } @@ -488,13 +671,7 @@ * to match up the caller's and callee's types. * <p> * This method is equivalent to {@link MethodHandles#convertArguments convertArguments}, - * except for method handles produced by {@link #withTypeHandler withTypeHandler}, - * in which case the specified type handler is used for calls to {@code asType}. - * <p> - * Note that the default behavior of {@code asType} only performs - * pairwise argument conversion and return value conversion. - * Because of this, unless the method handle has a type handler, - * the original type and new type must have the same number of arguments. + * except for variable arity method handles produced by {@link #asVarargsCollector asVarargsCollector}. * * @param newType the expected type of the new method handle * @return a method handle which delegates to {@code this} after performing @@ -508,14 +685,16 @@ } /** - * Produce a method handle which adapts, as its <i>target</i>, + * Make an adapter which accepts a trailing array argument + * and spreads its elements as positional arguments. + * The new method handle adapts, as its <i>target</i>, * the current method handle. The type of the adapter will be * the same as the type of the target, except that the final * {@code arrayLength} parameters of the target's type are replaced * by a single array parameter of type {@code arrayType}. * <p> * If the array element type differs from any of the corresponding - * argument types on original target, + * argument types on the original target, * the original target is adapted to take the array elements directly, * as if by a call to {@link #asType asType}. * <p> @@ -539,8 +718,9 @@ * @throws IllegalArgumentException if target does not have at least * {@code arrayLength} parameter types * @throws WrongMethodTypeException if the implied {@code asType} call fails + * @see #asCollector */ - public final MethodHandle asSpreader(Class<?> arrayType, int arrayLength) { + public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) { Class<?> arrayElement = arrayType.getComponentType(); if (arrayElement == null) throw newIllegalArgumentException("not an array type"); MethodType oldType = type(); @@ -553,13 +733,15 @@ } /** - * Produce a method handle which adapts, as its <i>target</i>, + * Make an adapter which accepts a given number of trailing + * positional arguments and collects them into an array argument. + * The new method handle adapts, as its <i>target</i>, * the current method handle. The type of the adapter will be * the same as the type of the target, except that a single trailing * parameter (usually of type {@code arrayType}) is replaced by * {@code arrayLength} parameters whose type is element type of {@code arrayType}. * <p> - * If the array type differs from the final argument type on original target, + * If the array type differs from the final argument type on the original target, * the original target is adapted to take the array type directly, * as if by a call to {@link #asType asType}. * <p> @@ -570,21 +752,31 @@ * What the target eventually returns is returned unchanged by the adapter. * <p> * (The array may also be a shared constant when {@code arrayLength} is zero.) - * @param arrayType usually {@code Object[]}, the type of the array argument which will collect the arguments + * <p> + * (<em>Note:</em> The {@code arrayType} is often identical to the last + * parameter type of the original target. + * It is an explicit argument for symmetry with {@code asSpreader}, and also + * to allow the target to use a simple {@code Object} as its last parameter type.) + * <p> + * In order to create a collecting adapter which is not restricted to a particular + * number of collected arguments, use {@link #asVarargsCollector asVarargsCollector} instead. + * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments * @param arrayLength the number of arguments to collect into a new array argument * @return a new method handle which collects some trailing argument * into an array, before calling the original method handle * @throws IllegalArgumentException if {@code arrayType} is not an array type - or {@code arrayType} is not assignable to this method handle's trailing parameter type - * @throws IllegalArgumentException if {@code arrayLength} is not - * a legal array size + * or {@code arrayType} is not assignable to this method handle's trailing parameter type, + * or {@code arrayLength} is not a legal array size * @throws WrongMethodTypeException if the implied {@code asType} call fails + * @see #asSpreader + * @see #asVarargsCollector */ - public final MethodHandle asCollector(Class<?> arrayType, int arrayLength) { + public MethodHandle asCollector(Class<?> arrayType, int arrayLength) { Class<?> arrayElement = arrayType.getComponentType(); if (arrayElement == null) throw newIllegalArgumentException("not an array type"); MethodType oldType = type(); int nargs = oldType.parameterCount(); + if (nargs == 0) throw newIllegalArgumentException("no trailing argument"); MethodType newType = oldType.dropParameterTypes(nargs-1, nargs); newType = newType.insertParameterTypes(nargs-1, java.util.Collections.<Class<?>>nCopies(arrayLength, arrayElement)); @@ -592,8 +784,185 @@ } /** - * Produce a method handle which binds the given argument - * to the current method handle as <i>target</i>. + * Make a <em>variable arity</em> adapter which is able to accept + * any number of trailing positional arguments and collect them + * into an array argument. + * <p> + * The type and behavior of the adapter will be the same as + * the type and behavior of the target, except that certain + * {@code invokeGeneric} and {@code asType} requests can lead to + * trailing positional arguments being collected into target's + * trailing parameter. + * Also, the last parameter type of the adapter will be + * {@code arrayType}, even if the target has a different + * last parameter type. + * <p> + * When called with {@link #invokeExact invokeExact}, the adapter invokes + * the target with no argument changes. + * (<em>Note:</em> This behavior is different from a + * {@linkplain #asCollector fixed arity collector}, + * since it accepts a whole array of indeterminate length, + * rather than a fixed number of arguments.) + * <p> + * When called with {@link #invokeGeneric invokeGeneric}, if the caller + * type is the same as the adapter, the adapter invokes the target as with + * {@code invokeExact}. + * (This is the normal behavior for {@code invokeGeneric} when types match.) + * <p> + * Otherwise, if the caller and adapter arity are the same, and the + * trailing parameter type of the caller is a reference type identical to + * or assignable to the trailing parameter type of the adapter, + * the arguments and return values are converted pairwise, + * as if by {@link MethodHandles#convertArguments convertArguments}. + * (This is also normal behavior for {@code invokeGeneric} in such a case.) + * <p> + * Otherwise, the arities differ, or the adapter's trailing parameter + * type is not assignable from the corresponding caller type. + * In this case, the adapter replaces all trailing arguments from + * the original trailing argument position onward, by + * a new array of type {@code arrayType}, whose elements + * comprise (in order) the replaced arguments. + * <p> + * The caller type must provides as least enough arguments, + * and of the correct type, to satisfy the target's requirement for + * positional arguments before the trailing array argument. + * Thus, the caller must supply, at a minimum, {@code N-1} arguments, + * where {@code N} is the arity of the target. + * Also, there must exist conversions from the incoming arguments + * to the target's arguments. + * As with other uses of {@code invokeGeneric}, if these basic + * requirements are not fulfilled, a {@code WrongMethodTypeException} + * may be thrown. + * <p> + * In all cases, what the target eventually returns is returned unchanged by the adapter. + * <p> + * In the final case, it is exactly as if the target method handle were + * temporarily adapted with a {@linkplain #asCollector fixed arity collector} + * to the arity required by the caller type. + * (As with {@code asCollector}, if the array length is zero, + * a shared constant may be used instead of a new array. + * If the implied call to {@code asCollector} would throw + * an {@code IllegalArgumentException} or {@code WrongMethodTypeException}, + * the call to the variable arity adapter must throw + * {@code WrongMethodTypeException}.) + * <p> + * The behavior of {@link #asType asType} is also specialized for + * variable arity adapters, to maintain the invariant that + * {@code invokeGeneric} is always equivalent to an {@code asType} + * call to adjust the target type, followed by {@code invokeExact}. + * Therefore, a variable arity adapter responds + * to an {@code asType} request by building a fixed arity collector, + * if and only if the adapter and requested type differ either + * in arity or trailing argument type. + * The resulting fixed arity collector has its type further adjusted + * (if necessary) to the requested type by pairwise conversion, + * as if by another application of {@code asType}. + * <p> + * When a method handle is obtained by executing an {@code ldc} instruction + * of a {@code CONSTANT_MethodHandle} constant, and the target method is marked + * as a variable arity method (with the modifier bit {@code 0x0080}), + * the method handle will accept multiple arities, as if the method handle + * constant were created by means of a call to {@code asVarargsCollector}. + * <p> + * In order to create a collecting adapter which collects a predetermined + * number of arguments, and whose type reflects this predetermined number, + * use {@link #asCollector asCollector} instead. + * <p> + * No method handle transformations produce new method handles with + * variable arity, unless they are documented as doing so. + * Therefore, besides {@code asVarargsCollector}, + * all methods in {@code MethodHandle} and {@code MethodHandles} + * will return a method handle with fixed arity, + * except in the cases where they are specified to return their original + * operand (e.g., {@code asType} of the method handle's own type). + * <p> + * Calling {@code asVarargsCollector} on a method handle which is already + * of variable arity will produce a method handle with the same type and behavior. + * It may (or may not) return the original variable arity method handle. + * <p> + * Here is an example, of a list-making variable arity method handle: + * <blockquote><pre> +MethodHandle asList = publicLookup() + .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)) + .asVarargsCollector(Object[].class); +assertEquals("[]", asList.invokeGeneric().toString()); +assertEquals("[1]", asList.invokeGeneric(1).toString()); +assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString()); +Object[] argv = { "three", "thee", "tee" }; +assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString()); +List ls = (List) asList.invokeGeneric((Object)argv); +assertEquals(1, ls.size()); +assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0))); + * </pre></blockquote> + * <p style="font-size:smaller;"> + * <em>Discussion:</em> + * These rules are designed as a dynamically-typed variation + * of the Java rules for variable arity methods. + * In both cases, callers to a variable arity method or method handle + * can either pass zero or more positional arguments, or else pass + * pre-collected arrays of any length. Users should be aware of the + * special role of the final argument, and of the effect of a + * type match on that final argument, which determines whether + * or not a single trailing argument is interpreted as a whole + * array or a single element of an array to be collected. + * Note that the dynamic type of the trailing argument has no + * effect on this decision, only a comparison between the static + * type descriptor of the call site and the type of the method handle.) + * <p style="font-size:smaller;"> + * As a result of the previously stated rules, the variable arity behavior + * of a method handle may be suppressed, by binding it to the exact invoker + * of its own type, as follows: + * <blockquote><pre> +MethodHandle vamh = publicLookup() + .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)) + .asVarargsCollector(Object[].class); +MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh); +assert(vamh.type().equals(mh.type())); +assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString()); +boolean failed = false; +try { mh.invokeGeneric(1,2,3); } +catch (WrongMethodTypeException ex) { failed = true; } +assert(failed); + * </pre></blockquote> + * This transformation has no behavioral effect if the method handle is + * not of variable arity. + * + * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments + * @return a new method handle which can collect any number of trailing arguments + * into an array, before calling the original method handle + * @throws IllegalArgumentException if {@code arrayType} is not an array type + * or {@code arrayType} is not assignable to this method handle's trailing parameter type + * @see #asCollector + * @see #isVarargsCollector + */ + public MethodHandle asVarargsCollector(Class<?> arrayType) { + Class<?> arrayElement = arrayType.getComponentType(); + if (arrayElement == null) throw newIllegalArgumentException("not an array type"); + return MethodHandles.asVarargsCollector(this, arrayType); + } + + /** + * Determine if this method handle + * supports {@linkplain #asVarargsCollector variable arity} calls. + * Such method handles arise from the following sources: + * <ul> + * <li>a call to {@linkplain #asVarargsCollector asVarargsCollector} + * <li>a call to a {@linkplain java.dyn.MethodHandles.Lookup lookup method} + * which resolves to a variable arity Java method or constructor + * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle} + * which resolves to a variable arity Java method or constructor + * </ul> + * @return true if this method handle accepts more than one arity of {@code invokeGeneric} calls + * @see #asVarargsCollector + */ + public boolean isVarargsCollector() { + return false; + } + + /** + * Bind a value {@code x} to the first argument of a method handle, without invoking it. + * The new method handle adapts, as its <i>target</i>, + * to the current method handle. * The type of the bound handle will be * the same as the type of the target, except that a single leading * reference parameter will be omitted. @@ -614,79 +983,27 @@ * to the leading parameter type of the target * @see MethodHandles#insertArguments */ - public final MethodHandle bindTo(Object x) { + public MethodHandle bindTo(Object x) { return MethodHandles.insertArguments(this, 0, x); } /** - * <em>PROVISIONAL API, WORK IN PROGRESS:</em> - * Create a new method handle with the same type as this one, - * but whose {@code asType} method invokes the given - * {@code typeHandler} on this method handle, - * instead of the standard {@code MethodHandles.convertArguments}. - * <p> - * The new method handle will have the same behavior as the - * old one when invoked by {@code invokeExact}. - * For {@code invokeGeneric} calls which exactly match - * the method type, the two method handles will also - * have the same behavior. - * For other {@code invokeGeneric} calls, the {@code typeHandler} - * will control the behavior of the new method handle. - * <p> - * Thus, a method handle with an {@code asType} handler can - * be configured to accept more than one arity of {@code invokeGeneric} - * call, and potentially every possible arity. - * It can also be configured to supply default values for - * optional arguments, when the caller does not specify them. - * <p> - * The given method handle must take two arguments and return - * one result. The result it returns must be a method handle - * of exactly the requested type. If the result returned by - * the target is null, a {@link NullPointerException} is thrown, - * else if the type of the target does not exactly match - * the requested type, a {@link WrongMethodTypeException} is thrown. - * <p> - * A method handle's type handler is not guaranteed to be called every - * time its {@code asType} or {@code invokeGeneric} method is called. - * If the implementation is faced is able to prove that an equivalent - * type handler call has already occurred (on the same two arguments), - * it may substitute the result of that previous invocation, without - * making a new invocation. Thus, type handlers should not (in general) - * perform significant side effects. - * <p> - * Therefore, the type handler is invoked as if by this code: + * Returns a string representation of the method handle, + * starting with the string {@code "MethodHandle"} and + * ending with the string representation of the method handle's type. + * In other words, this method returns a string equal to the value of: * <blockquote><pre> - * MethodHandle target = this; // original method handle - * MethodHandle adapter = ...; // adapted method handle - * MethodType requestedType = ...; // argument to asType() - * if (type().equals(requestedType)) - * return adapter; - * MethodHandle result = (MethodHandle) - * typeHandler.invokeGeneric(target, requestedType); - * if (!result.type().equals(requestedType)) - * throw new WrongMethodTypeException(); - * return result; + * "MethodHandle" + type().toString() * </pre></blockquote> * <p> - * For example, here is a list-making variable-arity method handle: - * <blockquote><pre> -MethodHandle makeEmptyList = MethodHandles.constant(List.class, Arrays.asList()); -MethodHandle asList = lookup() - .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)); -static MethodHandle collectingTypeHandler(MethodHandle base, MethodType newType) { - return asList.asCollector(Object[].class, newType.parameterCount()).asType(newType); -} -MethodHandle collectingTypeHandler = lookup() - .findStatic(lookup().lookupClass(), "collectingTypeHandler", - methodType(MethodHandle.class, MethodHandle.class, MethodType.class)); -MethodHandle makeAnyList = makeEmptyList.withTypeHandler(collectingTypeHandler); - -assertEquals("[]", makeAnyList.invokeGeneric().toString()); -assertEquals("[1]", makeAnyList.invokeGeneric(1).toString()); -assertEquals("[two, too]", makeAnyList.invokeGeneric("two", "too").toString()); - * <pre><blockquote> + * Note: Future releases of this API may add further information + * to the string representation. + * Therefore, the present syntax should not be parsed by applications. + * + * @return a string representation of the method handle */ - public MethodHandle withTypeHandler(MethodHandle typeHandler) { - return MethodHandles.withTypeHandler(this, typeHandler); + @Override + public String toString() { + return MethodHandleImpl.getNameString(IMPL_TOKEN, this); } }
--- a/jdk/src/share/classes/java/dyn/MethodHandles.java Tue Mar 01 15:24:46 2011 +0300 +++ b/jdk/src/share/classes/java/dyn/MethodHandles.java Sun Mar 06 20:32:49 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import sun.dyn.Access; import sun.dyn.MemberName; import sun.dyn.MethodHandleImpl; +import sun.dyn.WrapperInstance; import sun.dyn.util.ValueConversions; import sun.dyn.util.VerifyAccess; import sun.dyn.util.Wrapper; @@ -45,10 +46,10 @@ * This class consists exclusively of static methods that operate on or return * method handles. They fall into several categories: * <ul> - * <li>Factory methods which create method handles for methods and fields. - * <li>Invoker methods which can invoke method handles on dynamically typed arguments and/or varargs arrays. - * <li>Combinator methods, which combine or transforming pre-existing method handles into new ones. - * <li>Factory methods which create method handles that emulate other common JVM operations or control flow patterns. + * <li>Lookup methods which help create method handles for methods and fields. + * <li>Combinator methods, which combine or transform pre-existing method handles into new ones. + * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns. + * <li>Wrapper methods which can convert between method handles and other function-like "SAM types". * </ul> * <p> * @author John Rose, JSR 292 EG @@ -97,47 +98,155 @@ * when the creation requires access checking. * Method handles do not perform * access checks when they are called, but rather when they are created. - * (This is a major difference - * from reflective {@link Method}, which performs access checking - * against every caller, on every call.) * Therefore, method handle access * restrictions must be enforced when a method handle is created. * The caller class against which those restrictions are enforced * is known as the {@linkplain #lookupClass lookup class}. - * A lookup object embodies an - * authenticated lookup class, and can be used to create any number + * <p> + * A lookup class which needs to create method handles will call + * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself. + * When the {@code Lookup} factory object is created, the identity of the lookup class is + * determined, and securely stored in the {@code Lookup} object. + * The lookup class (or its delegates) may then use factory methods + * on the {@code Lookup} object to create method handles for access-checked members. + * This includes all methods, constructors, and fields which are allowed to the lookup class, + * even private ones. + * <p> + * The factory methods on a {@code Lookup} object correspond to all major + * use cases for methods, constructors, and fields. + * Here is a summary of the correspondence between these factory methods and + * the behavior the resulting method handles: + * <code> + * <table border=1 cellpadding=5 summary="lookup method behaviors"> + * <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td> + * <td>FT f;</td><td>(T) this.f;</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td> + * <td>static<br>FT f;</td><td>(T) C.f;</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td> + * <td>FT f;</td><td>this.f = x;</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td> + * <td>static<br>FT f;</td><td>C.f = arg;</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td> + * <td>T m(A*);</td><td>(T) this.m(arg*);</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td> + * <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td> + * <td>T m(A*);</td><td>(T) super.m(arg*);</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td> + * <td>C(A*);</td><td>(T) new C(arg*);</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td> + * <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td> + * <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> + * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td> + * <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td> + * </tr> + * <tr> + * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> + * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td> + * </tr> + * </table> + * </code> + * Here, the type {@code C} is the class or interface being searched for a member, + * documented as a parameter named {@code refc} in the lookup methods. + * The method or constructor type {@code MT} is composed from the return type {@code T} + * and the sequence of argument types {@code A*}. + * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}. + * The formal parameter {@code this} stands for the self-reference of type {@code C}; + * if it is present, it is always the leading argument to the method handle invocation. + * The name {@code arg} stands for all the other method handle arguments. + * In the code examples for the Core Reflection API, the name {@code thisOrNull} + * stands for a null reference if the accessed method or field is static, + * and {@code this} otherwise. + * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand + * for reflective objects corresponding to the given members. + * <p> + * The equivalence between looked-up method handles and underlying + * class members can break down in a few ways: + * <ul> + * <li>If {@code C} is not symbolically accessible from the lookup class's loader, + * the lookup can still succeed, even when there is no equivalent + * Java expression or bytecoded constant. + * <li>Likewise, if {@code T} or {@code MT} + * is not symbolically accessible from the lookup class's loader, + * the lookup can still succeed. + * For example, lookups for {@code MethodHandle.invokeExact} and + * {@code MethodHandle.invokeGeneric} will always succeed, regardless of requested type. + * <li>If there is a security manager installed, it can forbid the lookup + * on various grounds (<a href="#secmgr">see below</a>). + * By contrast, the {@code ldc} instruction is not subject to + * security manager checks. + * </ul> + * + * <h3><a name="access"></a>Access checking</h3> + * Access checks are applied in the factory methods of {@code Lookup}, + * when a method handle is created. + * This is a key difference from the Core Reflection API, since + * {@link java.lang.reflect.Method#invoke Method.invoke} + * performs access checking against every caller, on every call. + * <p> + * All access checks start from a {@code Lookup} object, which + * compares its recorded lookup class against all requests to + * create method handles. + * A single {@code Lookup} object can be used to create any number * of access-checked method handles, all checked against a single * lookup class. * <p> - * A class which needs to create method handles will call - * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself. - * It may then use this factory to create method handles on - * all of its methods, including private ones. - * It may also delegate the lookup (e.g., to a metaobject protocol) - * by passing the lookup object to other code. - * If this other code creates method handles, they will be access - * checked against the original lookup class, and not with any higher - * privileges. + * A {@code Lookup} object can be shared with other trusted code, + * such as a metaobject protocol. + * A shared {@code Lookup} object delegates the capability + * to create method handles on private members of the lookup class. + * Even if privileged code uses the {@code Lookup} object, + * the access checking is confined to the privileges of the + * original lookup class. * <p> - * Access checks only apply to named and reflected methods. - * Other method handle creation methods, such as - * {@link #convertArguments MethodHandles.convertArguments}, - * do not require any access checks, and can be done independently - * of any lookup class. - * <h3>How access errors are handled</h3> * A lookup can fail, because * the containing class is not accessible to the lookup class, or * because the desired class member is missing, or because the * desired class member is not accessible to the lookup class. - * It can also fail if a security manager is installed and refuses - * access. In any of these cases, an exception will be - * thrown from the attempted lookup. + * In any of these cases, a {@code ReflectiveOperationException} will be + * thrown from the attempted lookup. The exact class will be one of + * the following: + * <ul> + * <li>NoSuchMethodException — if a method is requested but does not exist + * <li>NoSuchFieldException — if a field is requested but does not exist + * <li>IllegalAccessException — if the member exists but an access check fails + * </ul> * <p> * In general, the conditions under which a method handle may be - * created for a method {@code M} are exactly as restrictive as the conditions - * under which the lookup class could have compiled a call to {@code M}. + * looked up for a method {@code M} are exactly equivalent to the conditions + * under which the lookup class could have compiled and resolved a call to {@code M}. + * And the effect of invoking the method handle resulting from the lookup + * is exactly equivalent to executing the compiled and resolved call to {@code M}. + * The same point is true of fields and constructors. * <p> - * In some cases, this access is obtained by the Java compiler by creating + * In some cases, access between nested classes is obtained by the Java compiler by creating * an wrapper method to access a private method of another class * in the same top-level declaration. * For example, a nested class {@code C.D} @@ -149,6 +258,61 @@ * A workaround for this limitation is the {@link Lookup#in Lookup.in} method, * which can transform a lookup on {@code C.E} into one on any of those other * classes, without special elevation of privilege. + * <p> + * Although bytecode instructions can only refer to classes in + * a related class loader, this API can search for methods in any + * class, as long as a reference to its {@code Class} object is + * available. Such cross-loader references are also possible with the + * Core Reflection API, and are impossible to bytecode instructions + * such as {@code invokestatic} or {@code getfield}. + * There is a {@linkplain java.lang.SecurityManager security manager API} + * to allow applications to check such cross-loader references. + * These checks apply to both the {@code MethodHandles.Lookup} API + * and the Core Reflection API + * (as found on {@link java.lang.Class Class}). + * <p> + * Access checks only apply to named and reflected methods, + * constructors, and fields. + * Other method handle creation methods, such as + * {@link #convertArguments MethodHandles.convertArguments}, + * do not require any access checks, and are done + * with static methods of {@link MethodHandles}, + * independently of any {@code Lookup} object. + * + * <h3>Security manager interactions</h3> + * <a name="secmgr"></a> + * If a security manager is present, member lookups are subject to + * additional checks. + * From one to four calls are made to the security manager. + * Any of these calls can refuse access by throwing a + * {@link java.lang.SecurityException SecurityException}. + * Define {@code smgr} as the security manager, + * {@code refc} as the containing class in which the member + * is being sought, and {@code defc} as the class in which the + * member is actually defined. + * The calls are made according to the following rules: + * <ul> + * <li>In all cases, {@link SecurityManager#checkMemberAccess + * smgr.checkMemberAccess(refc, Member.PUBLIC)} is called. + * <li>If the class loader of the lookup class is not + * the same as or an ancestor of the class loader of {@code refc}, + * then {@link SecurityManager#checkPackageAccess + * smgr.checkPackageAccess(refcPkg)} is called, + * where {@code refcPkg} is the package of {@code refc}. + * <li>If the retrieved member is not public, + * {@link SecurityManager#checkMemberAccess + * smgr.checkMemberAccess(defc, Member.DECLARED)} is called. + * (Note that {@code defc} might be the same as {@code refc}.) + * <li>If the retrieved member is not public, + * and if {@code defc} and {@code refc} are in different class loaders, + * and if the class loader of the lookup class is not + * the same as or an ancestor of the class loader of {@code defc}, + * then {@link SecurityManager#checkPackageAccess + * smgr.checkPackageAccess(defcPkg)} is called, + * where {@code defcPkg} is the package of {@code defc}. + * </ul> + * In all cases, the requesting class presented to the security + * manager will be the lookup class from the current {@code Lookup} object. */ public static final class Lookup { @@ -194,12 +358,12 @@ return (mods != 0) ? mods : PACKAGE; } - /** Which class is performing the lookup? It is this class against + /** Tells which class is performing the lookup. It is this class against * which checks are performed for visibility and access permissions. * <p> * The class implies a maximum level of access permission, * but the permissions may be additionally limited by the bitmask - * {@link #lookupModes}, which controls whether non-public members + * {@link #lookupModes lookupModes}, which controls whether non-public members * can be accessed. */ public Class<?> lookupClass() { @@ -211,7 +375,7 @@ return (allowedModes == TRUSTED) ? null : lookupClass; } - /** Which types of members can this lookup object produce? + /** Tells which access-protection classes of members this lookup object can produce. * The result is a bit-mask of the bits * {@linkplain #PUBLIC PUBLIC (0x01)}, * {@linkplain #PRIVATE PRIVATE (0x02)}, @@ -257,7 +421,7 @@ } /** - * Create a lookup on the specified new lookup class. + * Creates a lookup on the specified new lookup class. * The resulting object will report the specified * class as its own {@link #lookupClass lookupClass}. * <p> @@ -275,6 +439,10 @@ * then no members, not even public members, will be accessible. * (In all other cases, public members will continue to be accessible.) * </ul> + * + * @param requestedLookupClass the desired lookup class for the new lookup object + * @return a lookup object which reports the desired lookup class + * @throws NullPointerException if the argument is null */ public Lookup in(Class<?> requestedLookupClass) { requestedLookupClass.getClass(); // null check @@ -322,11 +490,12 @@ } /** - * Display the name of the class from which lookups are to be made. + * Displays the name of the class from which lookups are to be made. * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.) * If there are restrictions on the access permitted to this lookup, * this is indicated by adding a suffix to the class name, consisting - * of a slash and a keyword. The keyword is chosen as follows: + * of a slash and a keyword. The keyword represents the strongest + * allowed access, and is chosen as follows: * <ul> * <li>If no access is allowed, the suffix is "/noaccess". * <li>If only public access is allowed, the suffix is "/public". @@ -337,26 +506,37 @@ * access (public, package, private, and protected) is allowed. * In this case, no suffix is added. * This is true only of an object obtained originally from - * {@link java.dyn.MethodHandles#lookup() MethodHandles.lookup}. - * Objects created by {@link java.dyn.MethodHandles.Lookup#in() Lookup#in} + * {@link java.dyn.MethodHandles#lookup MethodHandles.lookup}. + * Objects created by {@link java.dyn.MethodHandles.Lookup#in Lookup.in} * always have restricted access, and will display a suffix. + * <p> + * (It may seem strange that protected access should be + * stronger than private access. Viewed independently from + * package access, protected access is the first to be lost, + * because it requires a direct subclass relationship between + * caller and callee.) + * @see #in */ @Override public String toString() { String cname = lookupClass.getName(); switch (allowedModes) { - case TRUSTED: - return "/trusted"; // internal only + case 0: // no privileges + return cname + "/noaccess"; case PUBLIC: return cname + "/public"; case PUBLIC|PACKAGE: return cname + "/package"; - case 0: // no privileges - return cname + "/noaccess"; + case ALL_MODES & ~PROTECTED: + return cname + "/private"; case ALL_MODES: return cname; - default: - return cname + "/private"; + case TRUSTED: + return "/trusted"; // internal only; not exported + default: // Should not happen, but it's a bitfield... + cname = cname + "/" + Integer.toHexString(allowedModes); + assert(false) : cname; + return cname; } } @@ -371,29 +551,37 @@ } /** - * Produce a method handle for a static method. + * Produces a method handle for a static method. * The type of the method handle will be that of the method. * (Since static methods do not take receivers, there is no * additional receiver argument inserted into the method handle type, - * as there would be with {@link #findVirtual} or {@link #findSpecial}.) + * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.) * The method and all its argument types must be accessible to the lookup class. * If the method's class has not yet been initialized, that is done * immediately, before the method handle is returned. + * <p> + * The returned method handle will have + * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if + * the method's variable arity modifier bit ({@code 0x0080}) is set. * @param refc the class from which the method is accessed * @param name the name of the method * @param type the type of the method * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the method does not exist + * @throws IllegalAccessException if access checking fails, or if the method is not {@code static} + * @exception SecurityException if a security manager is present and it + * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> + * @throws NullPointerException if any argument is null */ public - MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoAccessException { + MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(refc, name, type, true); checkMethod(refc, method, true); return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull()); } /** - * Produce a method handle for a virtual method. + * Produces a method handle for a virtual method. * The type of the method handle will be that of the method, * with the receiver type (usually {@code refc}) prepended. * The method and all its argument types must be accessible to the lookup class. @@ -403,13 +591,31 @@ * implementation to enter. * (The dispatching action is identical with that performed by an * {@code invokevirtual} or {@code invokeinterface} instruction.) + * <p> + * The returned method handle will have + * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if + * the method's variable arity modifier bit ({@code 0x0080}) is set. + * <p> + * Because of the general equivalence between {@code invokevirtual} + * instructions and method handles produced by {@code findVirtual}, + * if the class is {@code MethodHandle} and the name string is + * {@code invokeExact} or {@code invokeGeneric}, the resulting + * method handle is equivalent to one produced by + * {@link java.dyn.MethodHandles#exactInvoker MethodHandles.exactInvoker} or + * {@link java.dyn.MethodHandles#genericInvoker MethodHandles.genericInvoker} + * with the same {@code type} argument. + * * @param refc the class or interface from which the method is accessed * @param name the name of the method * @param type the type of the method, with the receiver argument omitted * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the method does not exist + * @throws IllegalAccessException if access checking fails, or if the method is {@code static} + * @exception SecurityException if a security manager is present and it + * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> + * @throws NullPointerException if any argument is null */ - public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoAccessException { + public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(refc, name, type, false); checkMethod(refc, method, false); MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull()); @@ -417,7 +623,7 @@ } /** - * Produce a method handle which creates an object and initializes it, using + * Produces a method handle which creates an object and initializes it, using * the constructor of the specified type. * The parameter types of the method handle will be those of the constructor, * while the return type will be a reference to the constructor's class. @@ -426,23 +632,47 @@ * immediately, before the method handle is returned. * <p> * Note: The requested type must have a return type of {@code void}. - * This is consistent with the JVM's treatment of constructor signatures. + * This is consistent with the JVM's treatment of constructor type descriptors. + * <p> + * The returned method handle will have + * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if + * the constructor's variable arity modifier bit ({@code 0x0080}) is set. * @param refc the class or interface from which the method is accessed * @param type the type of the method, with the receiver argument omitted, and a void return type * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the constructor does not exist + * @throws IllegalAccessException if access checking fails + * @exception SecurityException if a security manager is present and it + * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> + * @throws NullPointerException if any argument is null */ - public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoAccessException { + public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { String name = "<init>"; MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull()); assert(ctor.isConstructor()); checkAccess(refc, ctor); MethodHandle rawMH = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull()); - return MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawMH); + MethodHandle allocMH = MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawMH); + return fixVarargs(allocMH, rawMH); + } + + /** Return a version of MH which matches matchMH w.r.t. isVarargsCollector. */ + private static MethodHandle fixVarargs(MethodHandle mh, MethodHandle matchMH) { + boolean va1 = mh.isVarargsCollector(); + boolean va2 = matchMH.isVarargsCollector(); + if (va1 == va2) { + return mh; + } else if (va2) { + MethodType type = mh.type(); + int arity = type.parameterCount(); + return mh.asVarargsCollector(type.parameterType(arity-1)); + } else { + throw new InternalError("already varargs, but template is not: "+mh); + } } /** - * Produce an early-bound method handle for a virtual method, + * Produces an early-bound method handle for a virtual method, * as if called from an {@code invokespecial} * instruction from {@code caller}. * The type of the method handle will be that of the method, @@ -458,15 +688,23 @@ * If the explicitly specified caller class is not identical with the * lookup class, or if this lookup object does not have private access * privileges, the access fails. + * <p> + * The returned method handle will have + * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if + * the method's variable arity modifier bit ({@code 0x0080}) is set. * @param refc the class or interface from which the method is accessed * @param name the name of the method (which must not be "<init>") * @param type the type of the method, with the receiver argument omitted * @param specialCaller the proposed calling class to perform the {@code invokespecial} * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the method does not exist + * @throws IllegalAccessException if access checking fails + * @exception SecurityException if a security manager is present and it + * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> + * @throws NullPointerException if any argument is null */ public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, - Class<?> specialCaller) throws NoAccessException { + Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { checkSpecialCaller(specialCaller); MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller); checkMethod(refc, method, false); @@ -475,69 +713,89 @@ } /** - * Produce a method handle giving read access to a non-static field. + * Produces a method handle giving read access to a non-static field. * The type of the method handle will have a return type of the field's * value type. * The method handle's single argument will be the instance containing * the field. * Access checking is performed immediately on behalf of the lookup class. + * @param refc the class or interface from which the method is accessed * @param name the field's name * @param type the field's type * @return a method handle which can load values from the field - * @exception NoAccessException if access checking fails + * @throws NoSuchFieldException if the field does not exist + * @throws IllegalAccessException if access checking fails, or if the field is {@code static} + * @exception SecurityException if a security manager is present and it + * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> + * @throws NullPointerException if any argument is null */ - public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException { + public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { return makeAccessor(refc, name, type, false, false); } /** - * Produce a method handle giving write access to a non-static field. + * Produces a method handle giving write access to a non-static field. * The type of the method handle will have a void return type. * The method handle will take two arguments, the instance containing * the field, and the value to be stored. * The second argument will be of the field's value type. * Access checking is performed immediately on behalf of the lookup class. + * @param refc the class or interface from which the method is accessed * @param name the field's name * @param type the field's type * @return a method handle which can store values into the field - * @exception NoAccessException if access checking fails + * @throws NoSuchFieldException if the field does not exist + * @throws IllegalAccessException if access checking fails, or if the field is {@code static} + * @exception SecurityException if a security manager is present and it + * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> + * @throws NullPointerException if any argument is null */ - public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException { + public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { return makeAccessor(refc, name, type, false, true); } /** - * Produce a method handle giving read access to a static field. + * Produces a method handle giving read access to a static field. * The type of the method handle will have a return type of the field's * value type. * The method handle will take no arguments. * Access checking is performed immediately on behalf of the lookup class. + * @param refc the class or interface from which the method is accessed * @param name the field's name * @param type the field's type * @return a method handle which can load values from the field - * @exception NoAccessException if access checking fails + * @throws NoSuchFieldException if the field does not exist + * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} + * @exception SecurityException if a security manager is present and it + * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> + * @throws NullPointerException if any argument is null */ - public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException { + public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { return makeAccessor(refc, name, type, true, false); } /** - * Produce a method handle giving write access to a static field. + * Produces a method handle giving write access to a static field. * The type of the method handle will have a void return type. * The method handle will take a single * argument, of the field's value type, the value to be stored. * Access checking is performed immediately on behalf of the lookup class. + * @param refc the class or interface from which the method is accessed * @param name the field's name * @param type the field's type * @return a method handle which can store values into the field - * @exception NoAccessException if access checking fails + * @throws NoSuchFieldException if the field does not exist + * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} + * @exception SecurityException if a security manager is present and it + * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> + * @throws NullPointerException if any argument is null */ - public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException { + public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { return makeAccessor(refc, name, type, true, true); } /** - * Produce an early-bound method handle for a non-static method. + * Produces an early-bound method handle for a non-static method. * The receiver must have a supertype {@code defc} in which a method * of the given name and type is accessible to the lookup class. * The method and all its argument types must be accessible to the lookup class. @@ -547,28 +805,47 @@ * so that every call to the method handle will invoke the * requested method on the given receiver. * <p> - * This is equivalent to the following expression: - * <code> - * {@link #insertArguments insertArguments}({@link #findVirtual findVirtual}(defc, name, type), receiver) - * </code> + * The returned method handle will have + * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if + * the method's variable arity modifier bit ({@code 0x0080}) is set + * <em>and</em> the trailing array argument is not the only argument. + * (If the trailing array argument is the only argument, + * the given receiver value will be bound to it.) + * <p> + * This is equivalent to the following code: + * <blockquote><pre> +MethodHandle mh0 = {@link #findVirtual findVirtual}(defc, name, type); +MethodHandle mh1 = mh0.{@link MethodHandle#bindTo bindTo}(receiver); +MethodType mt1 = mh1.type(); +if (mh0.isVarargsCollector() && mt1.parameterCount() > 0) { + mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1)); +return mh1; + * </pre></blockquote> * where {@code defc} is either {@code receiver.getClass()} or a super * type of that class, in which the requested method is accessible * to the lookup class. + * (Note that {@code bindTo} does not preserve variable arity.) * @param receiver the object from which the method is accessed * @param name the name of the method * @param type the type of the method, with the receiver argument omitted * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the method does not exist + * @throws IllegalAccessException if access checking fails + * @exception SecurityException if a security manager is present and it + * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> + * @throws NullPointerException if any argument is null */ - public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException { + public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { Class<? extends Object> refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(refc, name, type, false); checkMethod(refc, method, false); MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull()); MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver); if (bmh == null) - throw newNoAccessException(method, lookupClass()); - return bmh; + throw newNoAccessException(method, this); + if (dmh.type().parameterCount() == 0) + return dmh; // bound the trailing parameter; no varargs possible + return fixVarargs(bmh, dmh); }