# HG changeset patch # User apetrusenko # Date 1238674922 25200 # Node ID a80d48f6fde19a1f25bebc5c0bb128e1778115da # Parent d3676b4cb78c62057456bc65bf4dc445d1c5825d# Parent cea947c8a9881f8236e22957caf4a3339881a6fe Merge diff -r cea947c8a988 -r a80d48f6fde1 .hgtags --- a/.hgtags Sat Mar 28 15:47:29 2009 -0700 +++ b/.hgtags Thu Apr 02 05:22:02 2009 -0700 @@ -25,3 +25,4 @@ bcb33806d186561c781992e5f4d8a90bb033f9f0 jdk7-b48 8b22ccb5aba2c6c11bddf6488a7bb7ef5b4bf2be jdk7-b49 dae503d9f04c1a11e182dbf7f770509c28dc0609 jdk7-b50 +2581d90c6c9b2012da930eb4742add94a03069a0 jdk7-b51 diff -r cea947c8a988 -r a80d48f6fde1 agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java Sat Mar 28 15:47:29 2009 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java Thu Apr 02 05:22:02 2009 -0700 @@ -46,12 +46,18 @@ Type type = db.lookupType("StubRoutines"); callStubReturnAddressField = type.getAddressField("_call_stub_return_address"); - // Only some platforms have specif return from compiled to call_stub + // Only some platforms have specific return from compiled to call_stub try { - callStubCompiledReturnAddressField = type.getAddressField("_call_stub_compiled_return"); + 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() { diff -r cea947c8a988 -r a80d48f6fde1 agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Sat Mar 28 15:47:29 2009 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Thu Apr 02 05:22:02 2009 -0700 @@ -347,6 +347,7 @@ for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { ((Observer) iter.next()).update(null, null); } + } /** This is used by the debugging system */ diff -r cea947c8a988 -r a80d48f6fde1 make/hotspot_version --- a/make/hotspot_version Sat Mar 28 15:47:29 2009 -0700 +++ b/make/hotspot_version Thu Apr 02 05:22:02 2009 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=15 HS_MINOR_VER=0 -HS_BUILD_NUMBER=03 +HS_BUILD_NUMBER=04 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 diff -r cea947c8a988 -r a80d48f6fde1 make/windows/build_vm_def.sh --- a/make/windows/build_vm_def.sh Sat Mar 28 15:47:29 2009 -0700 +++ b/make/windows/build_vm_def.sh Thu Apr 02 05:22:02 2009 -0700 @@ -52,6 +52,19 @@ RM="$MKS_HOME/rm.exe" DUMPBIN="link.exe /dump" +# When called from IDE the first param should contain the link version, otherwise may be nill +if [ "x$1" != "x" ]; then +LINK_VER="$1" +fi + +if [ "x$LINK_VER" != "x800" -a "x$LINK_VER" != "x900" ]; then $DUMPBIN /symbols *.obj | "$GREP" "??_7.*@@6B@" | "$AWK" '{print $7}' | "$SORT" | "$UNIQ" > vm2.def +else +# Can't use pipes when calling cl.exe or link.exe from IDE. Using transit file vm3.def +$DUMPBIN /OUT:vm3.def /symbols *.obj +"$CAT" vm3.def | "$GREP" "??_7.*@@6B@" | "$AWK" '{print $7}' | "$SORT" | "$UNIQ" > vm2.def +"$RM" -f vm3.def +fi + "$CAT" vm1.def vm2.def > vm.def "$RM" -f vm1.def vm2.def diff -r cea947c8a988 -r a80d48f6fde1 make/windows/create.bat --- a/make/windows/create.bat Sat Mar 28 15:47:29 2009 -0700 +++ b/make/windows/create.bat Thu Apr 02 05:22:02 2009 -0700 @@ -72,12 +72,20 @@ for /F %%i in ('sh %HotSpotWorkSpace%/make/windows/get_msc_ver.sh') do set %%i echo ************************************************************** +set ProjectFile=vm.vcproj if "%MSC_VER%" == "1200" ( set ProjectFile=vm.dsp echo Will generate VC6 project {unsupported} ) else ( -set ProjectFile=vm.vcproj -echo Will generate VC7 project +if "%MSC_VER%" == "1400" ( +echo Will generate VC8 {Visual Studio 2005} +) else ( +if "%MSC_VER%" == "1500" ( +echo Will generate VC9 {Visual Studio 2008} +) else ( +echo Will generate VC7 project {Visual Studio 2003 .NET} +) +) ) echo %ProjectFile% echo ************************************************************** diff -r cea947c8a988 -r a80d48f6fde1 make/windows/makefiles/adlc.make --- a/make/windows/makefiles/adlc.make Sat Mar 28 15:47:29 2009 -0700 +++ b/make/windows/makefiles/adlc.make Thu Apr 02 05:22:02 2009 -0700 @@ -46,6 +46,7 @@ ADLCFLAGS=-q -T -U_LP64 !endif +CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE CPP_INCLUDE_DIRS=\ /I "..\generated" \ diff -r cea947c8a988 -r a80d48f6fde1 make/windows/makefiles/compile.make --- a/make/windows/makefiles/compile.make Sat Mar 28 15:47:29 2009 -0700 +++ b/make/windows/makefiles/compile.make Thu Apr 02 05:22:02 2009 -0700 @@ -170,8 +170,6 @@ # Manifest Tool - used in VS2005 and later to adjust manifests stored # as resources inside build artifacts. MT=mt.exe -# VS2005 and later restricts the use of certain libc functions without this -CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_DEPRECATE !endif !if "$(COMPILER_NAME)" == "VS2008" @@ -183,8 +181,6 @@ # Manifest Tool - used in VS2005 and later to adjust manifests stored # as resources inside build artifacts. MT=mt.exe -# VS2005 and later restricts the use of certain libc functions without this -CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_DEPRECATE !endif # Compile for space above time. diff -r cea947c8a988 -r a80d48f6fde1 make/windows/makefiles/makedeps.make --- a/make/windows/makefiles/makedeps.make Sat Mar 28 15:47:29 2009 -0700 +++ b/make/windows/makefiles/makedeps.make Thu Apr 02 05:22:02 2009 -0700 @@ -48,6 +48,8 @@ $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatform.java \ $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC6.java \ $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC7.java \ + $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC8.java \ + $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC9.java \ $(WorkSpace)\src\share\tools\MakeDeps\Util.java \ $(WorkSpace)\src\share\tools\MakeDeps\BuildConfig.java \ $(WorkSpace)\src\share\tools\MakeDeps\ArgsParser.java @@ -121,7 +123,7 @@ -additionalFile includeDB_gc_shared \ -additionalFile includeDB_gc_serial \ -additionalGeneratedFile $(HOTSPOTBUILDSPACE)\%f\%b vm.def \ - -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh" \ + -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \ $(MakeDepsIncludesPRIVATE) # Add in build-specific options diff -r cea947c8a988 -r a80d48f6fde1 make/windows/makefiles/rules.make --- a/make/windows/makefiles/rules.make Sat Mar 28 15:47:29 2009 -0700 +++ b/make/windows/makefiles/rules.make Thu Apr 02 05:22:02 2009 -0700 @@ -42,10 +42,23 @@ BOOT_JAVA_HOME= !endif +ProjectFile=vm.vcproj + !if "$(MSC_VER)" == "1200" + VcVersion=VC6 ProjectFile=vm.dsp + +!elseif "$(MSC_VER)" == "1400" + +VcVersion=VC8 + +!elseif "$(MSC_VER)" == "1500" + +VcVersion=VC9 + !else + VcVersion=VC7 -ProjectFile=vm.vcproj + !endif diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/sparc/vm/assembler_sparc.cpp --- a/src/cpu/sparc/vm/assembler_sparc.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2615,12 +2615,12 @@ } } -RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, - Register tmp, - int offset) { +RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, + Register tmp, + int offset) { intptr_t value = *delayed_value_addr; if (value != 0) - return RegisterConstant(value + offset); + return RegisterOrConstant(value + offset); // load indirectly to solve generation ordering problem Address a(tmp, (address) delayed_value_addr); @@ -2634,11 +2634,11 @@ if (offset != 0) add(tmp, offset, tmp); - return RegisterConstant(tmp); + return RegisterOrConstant(tmp); } -void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { +void MacroAssembler::regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { assert(dest.register_or_noreg() != G0, "lost side effect"); if ((src.is_constant() && src.as_constant() == 0) || (src.is_register() && src.as_register() == G0)) { @@ -2647,15 +2647,15 @@ add(dest.as_register(), ensure_rs2(src, temp), dest.as_register()); } else if (src.is_constant()) { intptr_t res = dest.as_constant() + src.as_constant(); - dest = RegisterConstant(res); // side effect seen by caller + dest = RegisterOrConstant(res); // side effect seen by caller } else { assert(temp != noreg, "cannot handle constant += register"); add(src.as_register(), ensure_rs2(dest, temp), temp); - dest = RegisterConstant(temp); // side effect seen by caller + dest = RegisterOrConstant(temp); // side effect seen by caller } } -void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { +void MacroAssembler::regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { assert(dest.register_or_noreg() != G0, "lost side effect"); if (!is_simm13(src.constant_or_zero())) src = (src.as_constant() & 0xFF); @@ -2666,12 +2666,12 @@ sll_ptr(dest.as_register(), src, dest.as_register()); } else if (src.is_constant()) { intptr_t res = dest.as_constant() << src.as_constant(); - dest = RegisterConstant(res); // side effect seen by caller + dest = RegisterOrConstant(res); // side effect seen by caller } else { assert(temp != noreg, "cannot handle constant <<= register"); set(dest.as_constant(), temp); sll_ptr(temp, src, temp); - dest = RegisterConstant(temp); // side effect seen by caller + dest = RegisterOrConstant(temp); // side effect seen by caller } } @@ -2683,7 +2683,7 @@ // On failure, execution transfers to the given label. void MacroAssembler::lookup_interface_method(Register recv_klass, Register intf_klass, - RegisterConstant itable_index, + RegisterOrConstant itable_index, Register method_result, Register scan_temp, Register sethi_temp, @@ -2720,7 +2720,7 @@ add(recv_klass, scan_temp, scan_temp); // Adjust recv_klass by scaled itable_index, so we can free itable_index. - RegisterConstant itable_offset = itable_index; + RegisterOrConstant itable_offset = itable_index; regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes()); add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass); @@ -2805,7 +2805,7 @@ Label* L_success, Label* L_failure, Label* L_slow_path, - RegisterConstant super_check_offset, + RegisterOrConstant super_check_offset, Register instanceof_hack) { int sc_offset = (klassOopDesc::header_size() * HeapWordSize + Klass::secondary_super_cache_offset_in_bytes()); @@ -2867,7 +2867,7 @@ if (must_load_sco) { // The super check offset is always positive... lduw(super_klass, sco_offset, temp2_reg); - super_check_offset = RegisterConstant(temp2_reg); + super_check_offset = RegisterOrConstant(temp2_reg); } ld_ptr(sub_klass, super_check_offset, temp_reg); cmp(super_klass, temp_reg); @@ -4465,7 +4465,7 @@ } // Loading values by size and signed-ness -void MacroAssembler::load_sized_value(Register s1, RegisterConstant s2, Register d, +void MacroAssembler::load_sized_value(Register s1, RegisterOrConstant s2, Register d, int size_in_bytes, bool is_signed) { switch (size_in_bytes ^ (is_signed ? -1 : 0)) { case ~8: // fall through: diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/sparc/vm/assembler_sparc.hpp --- a/src/cpu/sparc/vm/assembler_sparc.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1088,8 +1088,8 @@ inline void add( Register s1, Register s2, Register d ); inline void add( Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none); inline void add( Register s1, int simm13a, Register d, RelocationHolder const& rspec); - inline void add( Register s1, RegisterConstant s2, Register d, int offset = 0); - inline void add( const Address& a, Register d, int offset = 0); + inline void add( Register s1, RegisterOrConstant s2, Register d, int offset = 0); + inline void add( const Address& a, Register d, int offset = 0); void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void addcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } @@ -1305,15 +1305,15 @@ inline void ld( const Address& a, Register d, int offset = 0 ); inline void ldd( const Address& a, Register d, int offset = 0 ); - inline void ldub( Register s1, RegisterConstant s2, Register d ); - inline void ldsb( Register s1, RegisterConstant s2, Register d ); - inline void lduh( Register s1, RegisterConstant s2, Register d ); - inline void ldsh( Register s1, RegisterConstant s2, Register d ); - inline void lduw( Register s1, RegisterConstant s2, Register d ); - inline void ldsw( Register s1, RegisterConstant s2, Register d ); - inline void ldx( Register s1, RegisterConstant s2, Register d ); - inline void ld( Register s1, RegisterConstant s2, Register d ); - inline void ldd( Register s1, RegisterConstant s2, Register d ); + inline void ldub( Register s1, RegisterOrConstant s2, Register d ); + inline void ldsb( Register s1, RegisterOrConstant s2, Register d ); + inline void lduh( Register s1, RegisterOrConstant s2, Register d ); + inline void ldsh( Register s1, RegisterOrConstant s2, Register d ); + inline void lduw( Register s1, RegisterOrConstant s2, Register d ); + inline void ldsw( Register s1, RegisterOrConstant s2, Register d ); + inline void ldx( Register s1, RegisterOrConstant s2, Register d ); + inline void ld( Register s1, RegisterOrConstant s2, Register d ); + inline void ldd( Register s1, RegisterOrConstant s2, Register d ); // pp 177 @@ -1535,12 +1535,12 @@ inline void st( Register d, const Address& a, int offset = 0 ); inline void std( Register d, const Address& a, int offset = 0 ); - inline void stb( Register d, Register s1, RegisterConstant s2 ); - inline void sth( Register d, Register s1, RegisterConstant s2 ); - inline void stw( Register d, Register s1, RegisterConstant s2 ); - inline void stx( Register d, Register s1, RegisterConstant s2 ); - inline void std( Register d, Register s1, RegisterConstant s2 ); - inline void st( Register d, Register s1, RegisterConstant s2 ); + inline void stb( Register d, Register s1, RegisterOrConstant s2 ); + inline void sth( Register d, Register s1, RegisterOrConstant s2 ); + inline void stw( Register d, Register s1, RegisterOrConstant s2 ); + inline void stx( Register d, Register s1, RegisterOrConstant s2 ); + inline void std( Register d, Register s1, RegisterOrConstant s2 ); + inline void st( Register d, Register s1, RegisterOrConstant s2 ); // pp 177 @@ -1859,7 +1859,7 @@ // Functions for isolating 64 bit shifts for LP64 inline void sll_ptr( Register s1, Register s2, Register d ); inline void sll_ptr( Register s1, int imm6a, Register d ); - inline void sll_ptr( Register s1, RegisterConstant s2, Register d ); + inline void sll_ptr( Register s1, RegisterOrConstant s2, Register d ); inline void srl_ptr( Register s1, Register s2, Register d ); inline void srl_ptr( Register s1, int imm6a, Register d ); @@ -1965,26 +1965,26 @@ // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's inline void ld_ptr( Register s1, Register s2, Register d ); inline void ld_ptr( Register s1, int simm13a, Register d); - inline void ld_ptr( Register s1, RegisterConstant s2, Register d ); + inline void ld_ptr( Register s1, RegisterOrConstant s2, Register d ); inline void ld_ptr( const Address& a, Register d, int offset = 0 ); inline void st_ptr( Register d, Register s1, Register s2 ); inline void st_ptr( Register d, Register s1, int simm13a); - inline void st_ptr( Register d, Register s1, RegisterConstant s2 ); + inline void st_ptr( Register d, Register s1, RegisterOrConstant s2 ); inline void st_ptr( Register d, const Address& a, int offset = 0 ); // ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's // st_long will perform st for 32 bit VM's and stx for 64 bit VM's inline void ld_long( Register s1, Register s2, Register d ); inline void ld_long( Register s1, int simm13a, Register d ); - inline void ld_long( Register s1, RegisterConstant s2, Register d ); + inline void ld_long( Register s1, RegisterOrConstant s2, Register d ); inline void ld_long( const Address& a, Register d, int offset = 0 ); inline void st_long( Register d, Register s1, Register s2 ); inline void st_long( Register d, Register s1, int simm13a ); - inline void st_long( Register d, Register s1, RegisterConstant s2 ); + inline void st_long( Register d, Register s1, RegisterOrConstant s2 ); inline void st_long( Register d, const Address& a, int offset = 0 ); // Loading values by size and signed-ness - void load_sized_value(Register s1, RegisterConstant s2, Register d, + void load_sized_value(Register s1, RegisterOrConstant s2, Register d, int size_in_bytes, bool is_signed); // Helpers for address formation. @@ -1994,11 +1994,11 @@ // is required, and becomes the result. // If dest is a register and src is a non-simm13 constant, // the temp argument is required, and is used to materialize the constant. - void regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, + void regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp = noreg ); - void regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, + void regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp = noreg ); - RegisterConstant ensure_rs2(RegisterConstant rs2, Register sethi_temp) { + RegisterOrConstant ensure_rs2(RegisterOrConstant rs2, Register sethi_temp) { guarantee(sethi_temp != noreg, "constant offset overflow"); if (is_simm13(rs2.constant_or_zero())) return rs2; // register or short constant @@ -2322,7 +2322,7 @@ // interface method calling void lookup_interface_method(Register recv_klass, Register intf_klass, - RegisterConstant itable_index, + RegisterOrConstant itable_index, Register method_result, Register temp_reg, Register temp2_reg, Label& no_such_interface); @@ -2341,7 +2341,7 @@ Label* L_success, Label* L_failure, Label* L_slow_path, - RegisterConstant super_check_offset = RegisterConstant(-1), + RegisterOrConstant super_check_offset = RegisterOrConstant(-1), Register instanceof_hack = noreg); // The rest of the type check; must be wired to a corresponding fast path. @@ -2381,7 +2381,7 @@ // stack overflow + shadow pages. Clobbers tsp and scratch registers. void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch); - virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset); + virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset); void verify_tlab(); diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/sparc/vm/assembler_sparc.inline.hpp --- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -143,45 +143,45 @@ inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); } #endif -inline void Assembler::ldub( Register s1, RegisterConstant s2, Register d) { +inline void Assembler::ldub( Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) ldsb(s1, s2.as_register(), d); else ldsb(s1, s2.as_constant(), d); } -inline void Assembler::ldsb( Register s1, RegisterConstant s2, Register d) { +inline void Assembler::ldsb( Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) ldsb(s1, s2.as_register(), d); else ldsb(s1, s2.as_constant(), d); } -inline void Assembler::lduh( Register s1, RegisterConstant s2, Register d) { +inline void Assembler::lduh( Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) ldsh(s1, s2.as_register(), d); else ldsh(s1, s2.as_constant(), d); } -inline void Assembler::ldsh( Register s1, RegisterConstant s2, Register d) { +inline void Assembler::ldsh( Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) ldsh(s1, s2.as_register(), d); else ldsh(s1, s2.as_constant(), d); } -inline void Assembler::lduw( Register s1, RegisterConstant s2, Register d) { +inline void Assembler::lduw( Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) ldsw(s1, s2.as_register(), d); else ldsw(s1, s2.as_constant(), d); } -inline void Assembler::ldsw( Register s1, RegisterConstant s2, Register d) { +inline void Assembler::ldsw( Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) ldsw(s1, s2.as_register(), d); else ldsw(s1, s2.as_constant(), d); } -inline void Assembler::ldx( Register s1, RegisterConstant s2, Register d) { +inline void Assembler::ldx( Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) ldx(s1, s2.as_register(), d); else ldx(s1, s2.as_constant(), d); } -inline void Assembler::ld( Register s1, RegisterConstant s2, Register d) { +inline void Assembler::ld( Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) ld(s1, s2.as_register(), d); else ld(s1, s2.as_constant(), d); } -inline void Assembler::ldd( Register s1, RegisterConstant s2, Register d) { +inline void Assembler::ldd( Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) ldd(s1, s2.as_register(), d); else ldd(s1, s2.as_constant(), d); } // form effective addresses this way: -inline void Assembler::add( Register s1, RegisterConstant s2, Register d, int offset) { +inline void Assembler::add( Register s1, RegisterOrConstant s2, Register d, int offset) { if (s2.is_register()) add(s1, s2.as_register(), d); else { add(s1, s2.as_constant() + offset, d); offset = 0; } if (offset != 0) add(d, offset, d); @@ -243,23 +243,23 @@ inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); } inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); } -inline void Assembler::stb( Register d, Register s1, RegisterConstant s2) { +inline void Assembler::stb( Register d, Register s1, RegisterOrConstant s2) { if (s2.is_register()) stb(d, s1, s2.as_register()); else stb(d, s1, s2.as_constant()); } -inline void Assembler::sth( Register d, Register s1, RegisterConstant s2) { +inline void Assembler::sth( Register d, Register s1, RegisterOrConstant s2) { if (s2.is_register()) sth(d, s1, s2.as_register()); else sth(d, s1, s2.as_constant()); } -inline void Assembler::stx( Register d, Register s1, RegisterConstant s2) { +inline void Assembler::stx( Register d, Register s1, RegisterOrConstant s2) { if (s2.is_register()) stx(d, s1, s2.as_register()); else stx(d, s1, s2.as_constant()); } -inline void Assembler::std( Register d, Register s1, RegisterConstant s2) { +inline void Assembler::std( Register d, Register s1, RegisterOrConstant s2) { if (s2.is_register()) std(d, s1, s2.as_register()); else std(d, s1, s2.as_constant()); } -inline void Assembler::st( Register d, Register s1, RegisterConstant s2) { +inline void Assembler::st( Register d, Register s1, RegisterOrConstant s2) { if (s2.is_register()) st(d, s1, s2.as_register()); else st(d, s1, s2.as_constant()); } @@ -308,7 +308,7 @@ #endif } -inline void MacroAssembler::ld_ptr( Register s1, RegisterConstant s2, Register d ) { +inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) { #ifdef _LP64 Assembler::ldx( s1, s2, d); #else @@ -340,7 +340,7 @@ #endif } -inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterConstant s2 ) { +inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) { #ifdef _LP64 Assembler::stx( d, s1, s2); #else @@ -373,7 +373,7 @@ #endif } -inline void MacroAssembler::ld_long( Register s1, RegisterConstant s2, Register d ) { +inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Register d ) { #ifdef _LP64 Assembler::ldx(s1, s2, d); #else @@ -405,7 +405,7 @@ #endif } -inline void MacroAssembler::st_long( Register d, Register s1, RegisterConstant s2 ) { +inline void MacroAssembler::st_long( Register d, Register s1, RegisterOrConstant s2 ) { #ifdef _LP64 Assembler::stx(d, s1, s2); #else @@ -455,7 +455,7 @@ #endif } -inline void MacroAssembler::sll_ptr( Register s1, RegisterConstant s2, Register d ) { +inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) { if (s2.is_register()) sll_ptr(s1, s2.as_register(), d); else sll_ptr(s1, s2.as_constant(), d); } diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2489,7 +2489,7 @@ __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, noreg, (need_slow_path ? &done : NULL), stub->entry(), NULL, - RegisterConstant(k->super_check_offset())); + RegisterOrConstant(k->super_check_offset())); } else { // perform the fast part of the checking logic __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, @@ -2550,14 +2550,14 @@ __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, noreg, (need_slow_path ? &done : NULL), (need_slow_path ? &done : NULL), NULL, - RegisterConstant(k->super_check_offset()), + RegisterOrConstant(k->super_check_offset()), dst); } else { assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers"); // perform the fast part of the checking logic __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, dst, &done, &done, NULL, - RegisterConstant(-1), + RegisterOrConstant(-1), dst); } if (need_slow_path) { diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/sparc/vm/globals_sparc.hpp --- a/src/cpu/sparc/vm/globals_sparc.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/sparc/vm/globals_sparc.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -46,6 +46,7 @@ define_pd_global(uintx, NewSize, ScaleForWordSize((2048 * K) + (2 * (64 * K)))); define_pd_global(intx, SurvivorRatio, 8); define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC +define_pd_global(intx, InlineSmallCode, 1500); #ifdef _LP64 // Stack slots are 2X larger in LP64 than in the 32 bit VM. define_pd_global(intx, ThreadStackSize, 1024); diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -817,21 +817,6 @@ Label _atomic_add_stub; // called from other stubs - // Support for void OrderAccess::fence(). - // - address generate_fence() { - StubCodeMark mark(this, "StubRoutines", "fence"); - address start = __ pc(); - - __ membar(Assembler::Membar_mask_bits(Assembler::LoadLoad | Assembler::LoadStore | - Assembler::StoreLoad | Assembler::StoreStore)); - __ retl(false); - __ delayed()->nop(); - - return start; - } - - //------------------------------------------------------------------------------------------------------------------------ // The following routine generates a subroutine to throw an asynchronous // UnknownError when an unsafe access gets a fault that could not be @@ -2861,7 +2846,6 @@ StubRoutines::_atomic_cmpxchg_ptr_entry = StubRoutines::_atomic_cmpxchg_entry; StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long(); StubRoutines::_atomic_add_ptr_entry = StubRoutines::_atomic_add_entry; - StubRoutines::_fence_entry = generate_fence(); #endif // COMPILER2 !=> _LP64 } diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/sparc/vm/vm_version_sparc.cpp --- a/src/cpu/sparc/vm/vm_version_sparc.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -62,7 +62,7 @@ if (is_niagara1()) { // Indirect branch is the same cost as direct if (FLAG_IS_DEFAULT(UseInlineCaches)) { - UseInlineCaches = false; + FLAG_SET_DEFAULT(UseInlineCaches, false); } #ifdef _LP64 // Single issue niagara1 is slower for CompressedOops @@ -79,15 +79,19 @@ #ifdef COMPILER2 // Indirect branch is the same cost as direct if (FLAG_IS_DEFAULT(UseJumpTables)) { - UseJumpTables = true; + FLAG_SET_DEFAULT(UseJumpTables, true); } // Single-issue, so entry and loop tops are // aligned on a single instruction boundary if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) { - InteriorEntryAlignment = 4; + FLAG_SET_DEFAULT(InteriorEntryAlignment, 4); } if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { - OptoLoopAlignment = 4; + FLAG_SET_DEFAULT(OptoLoopAlignment, 4); + } + if (is_niagara1_plus() && FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + // Use smaller prefetch distance on N2 + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256); } #endif } @@ -95,7 +99,7 @@ // Use hardware population count instruction if available. if (has_hardware_popc()) { if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { - UsePopCountInstruction = true; + FLAG_SET_DEFAULT(UsePopCountInstruction, true); } } diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/x86/vm/assembler_x86.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1438,26 +1438,12 @@ } } -// Serializes memory. +// Emit mfence instruction void Assembler::mfence() { - // Memory barriers are only needed on multiprocessors - if (os::is_MP()) { - if( LP64_ONLY(true ||) VM_Version::supports_sse2() ) { - emit_byte( 0x0F ); // MFENCE; faster blows no regs - emit_byte( 0xAE ); - emit_byte( 0xF0 ); - } else { - // All usable chips support "locked" instructions which suffice - // as barriers, and are much faster than the alternative of - // using cpuid instruction. We use here a locked add [esp],0. - // This is conveniently otherwise a no-op except for blowing - // flags (which we save and restore.) - pushf(); // Save eflags register - lock(); - addl(Address(rsp, 0), 0);// Assert the lock# signal here - popf(); // Restore eflags register - } - } + NOT_LP64(assert(VM_Version::supports_sse2(), "unsupported");) + emit_byte( 0x0F ); + emit_byte( 0xAE ); + emit_byte( 0xF0 ); } void Assembler::mov(Register dst, Register src) { @@ -7218,7 +7204,7 @@ // On failure, execution transfers to the given label. void MacroAssembler::lookup_interface_method(Register recv_klass, Register intf_klass, - RegisterConstant itable_index, + RegisterOrConstant itable_index, Register method_result, Register scan_temp, Label& L_no_such_interface) { @@ -7303,7 +7289,7 @@ Label* L_success, Label* L_failure, Label* L_slow_path, - RegisterConstant super_check_offset) { + RegisterOrConstant super_check_offset) { assert_different_registers(sub_klass, super_klass, temp_reg); bool must_load_sco = (super_check_offset.constant_or_zero() == -1); if (super_check_offset.is_register()) { @@ -7352,7 +7338,7 @@ if (must_load_sco) { // Positive movl does right thing on LP64. movl(temp_reg, super_check_offset_addr); - super_check_offset = RegisterConstant(temp_reg); + super_check_offset = RegisterOrConstant(temp_reg); } Address super_check_addr(sub_klass, super_check_offset, Address::times_1, 0); cmpptr(super_klass, super_check_addr); // load displayed supertype @@ -7550,12 +7536,12 @@ } -RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, - Register tmp, - int offset) { +RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, + Register tmp, + int offset) { intptr_t value = *delayed_value_addr; if (value != 0) - return RegisterConstant(value + offset); + return RegisterOrConstant(value + offset); // load indirectly to solve generation ordering problem movptr(tmp, ExternalAddress((address) delayed_value_addr)); @@ -7571,7 +7557,7 @@ if (offset != 0) addptr(tmp, offset); - return RegisterConstant(tmp); + return RegisterOrConstant(tmp); } diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/x86/vm/assembler_x86.hpp --- a/src/cpu/x86/vm/assembler_x86.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/x86/vm/assembler_x86.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -212,7 +212,7 @@ "inconsistent address"); } - Address(Register base, RegisterConstant index, ScaleFactor scale = times_1, int disp = 0) + Address(Register base, RegisterOrConstant index, ScaleFactor scale = times_1, int disp = 0) : _base (base), _index(index.register_or_noreg()), _scale(scale), @@ -256,7 +256,7 @@ "inconsistent address"); } - Address(Register base, RegisterConstant index, ScaleFactor scale, ByteSize disp) + Address(Register base, RegisterOrConstant index, ScaleFactor scale, ByteSize disp) : _base (base), _index(index.register_or_noreg()), _scale(scale), @@ -1068,15 +1068,23 @@ LoadLoad = 1 << 0 }; - // Serializes memory. + // Serializes memory and blows flags void membar(Membar_mask_bits order_constraint) { - // We only have to handle StoreLoad and LoadLoad - if (order_constraint & StoreLoad) { - // MFENCE subsumes LFENCE - mfence(); - } /* [jk] not needed currently: else if (order_constraint & LoadLoad) { - lfence(); - } */ + if (os::is_MP()) { + // We only have to handle StoreLoad + if (order_constraint & StoreLoad) { + // All usable chips support "locked" instructions which suffice + // as barriers, and are much faster than the alternative of + // using cpuid instruction. We use here a locked add [esp],0. + // This is conveniently otherwise a no-op except for blowing + // flags. + // Any change to this code may need to revisit other places in + // the code where this idiom is used, in particular the + // orderAccess code. + lock(); + addl(Address(rsp, 0), 0);// Assert the lock# signal here + } + } } void mfence(); @@ -1802,7 +1810,7 @@ // interface method calling void lookup_interface_method(Register recv_klass, Register intf_klass, - RegisterConstant itable_index, + RegisterOrConstant itable_index, Register method_result, Register scan_temp, Label& no_such_interface); @@ -1819,7 +1827,7 @@ Label* L_success, Label* L_failure, Label* L_slow_path, - RegisterConstant super_check_offset = RegisterConstant(-1)); + RegisterOrConstant super_check_offset = RegisterOrConstant(-1)); // The rest of the type check; must be wired to a corresponding fast path. // It does not repeat the fast path logic, so don't use it standalone. @@ -1883,9 +1891,9 @@ // stack overflow + shadow pages. Also, clobbers tmp void bang_stack_size(Register size, Register tmp); - virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, - Register tmp, - int offset); + virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, + Register tmp, + int offset); // Support for serializing memory accesses between threads void serialize_memory(Register thread, Register tmp); diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/x86/vm/globals_x86.hpp --- a/src/cpu/x86/vm/globals_x86.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/x86/vm/globals_x86.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -60,6 +60,7 @@ define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1)); #endif // AMD64 define_pd_global(intx, InlineFrequencyCount, 100); +define_pd_global(intx, InlineSmallCode, 1000); define_pd_global(intx, PreInflateSpin, 10); define_pd_global(intx, StackYellowPages, 2); diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -637,7 +637,7 @@ address generate_orderaccess_fence() { StubCodeMark mark(this, "StubRoutines", "orderaccess_fence"); address start = __ pc(); - __ mfence(); + __ membar(Assembler::StoreLoad); __ ret(0); return start; diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/x86/vm/x86_32.ad --- a/src/cpu/x86/vm/x86_32.ad Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/x86/vm/x86_32.ad Thu Apr 02 05:22:02 2009 -0700 @@ -4288,24 +4288,6 @@ emit_opcode(cbuf, 0xC8 + $src2$$reg); %} - enc_class enc_membar_acquire %{ - // Doug Lea believes this is not needed with current Sparcs and TSO. - // MacroAssembler masm(&cbuf); - // masm.membar(); - %} - - enc_class enc_membar_release %{ - // Doug Lea believes this is not needed with current Sparcs and TSO. - // MacroAssembler masm(&cbuf); - // masm.membar(); - %} - - enc_class enc_membar_volatile %{ - MacroAssembler masm(&cbuf); - masm.membar(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - %} - // Atomically load the volatile long enc_class enc_loadL_volatile( memory mem, stackSlotL dst ) %{ emit_opcode(cbuf,0xDF); @@ -7498,9 +7480,9 @@ ins_cost(400); size(0); - format %{ "MEMBAR-acquire" %} - ins_encode( enc_membar_acquire ); - ins_pipe(pipe_slow); + format %{ "MEMBAR-acquire ! (empty encoding)" %} + ins_encode(); + ins_pipe(empty); %} instruct membar_acquire_lock() %{ @@ -7519,9 +7501,9 @@ ins_cost(400); size(0); - format %{ "MEMBAR-release" %} - ins_encode( enc_membar_release ); - ins_pipe(pipe_slow); + format %{ "MEMBAR-release ! (empty encoding)" %} + ins_encode( ); + ins_pipe(empty); %} instruct membar_release_lock() %{ @@ -7535,12 +7517,22 @@ ins_pipe(empty); %} -instruct membar_volatile() %{ +instruct membar_volatile(eFlagsReg cr) %{ match(MemBarVolatile); + effect(KILL cr); ins_cost(400); - format %{ "MEMBAR-volatile" %} - ins_encode( enc_membar_volatile ); + format %{ + $$template + if (os::is_MP()) { + $$emit$$"LOCK ADDL [ESP + #0], 0\t! membar_volatile" + } else { + $$emit$$"MEMBAR-volatile ! (empty encoding)" + } + %} + ins_encode %{ + __ membar(Assembler::StoreLoad); + %} ins_pipe(pipe_slow); %} diff -r cea947c8a988 -r a80d48f6fde1 src/cpu/x86/vm/x86_64.ad --- a/src/cpu/x86/vm/x86_64.ad Sat Mar 28 15:47:29 2009 -0700 +++ b/src/cpu/x86/vm/x86_64.ad Thu Apr 02 05:22:02 2009 -0700 @@ -4162,33 +4162,6 @@ // done: %} - enc_class enc_membar_acquire - %{ - // [jk] not needed currently, if you enable this and it really - // emits code don't forget to the remove the "size(0)" line in - // membar_acquire() - // MacroAssembler masm(&cbuf); - // masm.membar(Assembler::Membar_mask_bits(Assembler::LoadStore | - // Assembler::LoadLoad)); - %} - - enc_class enc_membar_release - %{ - // [jk] not needed currently, if you enable this and it really - // emits code don't forget to the remove the "size(0)" line in - // membar_release() - // MacroAssembler masm(&cbuf); - // masm.membar(Assembler::Membar_mask_bits(Assembler::LoadStore | - // Assembler::StoreStore)); - %} - - enc_class enc_membar_volatile - %{ - MacroAssembler masm(&cbuf); - masm.membar(Assembler::Membar_mask_bits(Assembler::StoreLoad | - Assembler::StoreStore)); - %} - // Safepoint Poll. This polls the safepoint page, and causes an // exception if it is not readable. Unfortunately, it kills // RFLAGS in the process. @@ -7458,7 +7431,7 @@ ins_cost(0); size(0); - format %{ "MEMBAR-acquire" %} + format %{ "MEMBAR-acquire ! (empty encoding)" %} ins_encode(); ins_pipe(empty); %} @@ -7481,7 +7454,7 @@ ins_cost(0); size(0); - format %{ "MEMBAR-release" %} + format %{ "MEMBAR-release ! (empty encoding)" %} ins_encode(); ins_pipe(empty); %} @@ -7498,13 +7471,22 @@ ins_pipe(empty); %} -instruct membar_volatile() -%{ +instruct membar_volatile(rFlagsReg cr) %{ match(MemBarVolatile); + effect(KILL cr); ins_cost(400); - format %{ "MEMBAR-volatile" %} - ins_encode(enc_membar_volatile); + format %{ + $$template + if (os::is_MP()) { + $$emit$$"lock addl [rsp + #0], 0\t! membar_volatile" + } else { + $$emit$$"MEMBAR-volatile ! (empty encoding)" + } + %} + ins_encode %{ + __ membar(Assembler::StoreLoad); + %} ins_pipe(pipe_slow); %} diff -r cea947c8a988 -r a80d48f6fde1 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os/linux/vm/os_linux.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -2269,15 +2269,16 @@ // All it does is to check if there are enough free pages // left at the time of mmap(). This could be a potential // problem. -bool os::commit_memory(char* addr, size_t size) { - uintptr_t res = (uintptr_t) ::mmap(addr, size, - PROT_READ|PROT_WRITE|PROT_EXEC, +bool os::commit_memory(char* addr, size_t size, bool exec) { + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; + uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); return res != (uintptr_t) MAP_FAILED; } -bool os::commit_memory(char* addr, size_t size, size_t alignment_hint) { - return commit_memory(addr, size); +bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, + bool exec) { + return commit_memory(addr, size, exec); } void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } @@ -2417,8 +2418,7 @@ unsigned long* os::Linux::_numa_all_nodes; bool os::uncommit_memory(char* addr, size_t size) { - return ::mmap(addr, size, - PROT_READ|PROT_WRITE|PROT_EXEC, + return ::mmap(addr, size, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0) != MAP_FAILED; } @@ -2441,7 +2441,9 @@ flags |= MAP_FIXED; } - addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE|PROT_EXEC, + // Map uncommitted pages PROT_READ and PROT_WRITE, change access + // to PROT_EXEC if executable when we commit the page. + addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE, flags, -1, 0); if (addr != MAP_FAILED) { @@ -2582,7 +2584,9 @@ #define SHM_HUGETLB 04000 #endif -char* os::reserve_memory_special(size_t bytes, char* req_addr) { +char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) { + // "exec" is passed in but not used. Creating the shared image for + // the code cache doesn't have an SHM_X executable permission to check. assert(UseLargePages, "only for large pages"); key_t key = IPC_PRIVATE; diff -r cea947c8a988 -r a80d48f6fde1 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -2623,15 +2623,16 @@ return page_size; } -bool os::commit_memory(char* addr, size_t bytes) { +bool os::commit_memory(char* addr, size_t bytes, bool exec) { + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; size_t size = bytes; return - NULL != Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, - PROT_READ | PROT_WRITE | PROT_EXEC); -} - -bool os::commit_memory(char* addr, size_t bytes, size_t alignment_hint) { - if (commit_memory(addr, bytes)) { + NULL != Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot); +} + +bool os::commit_memory(char* addr, size_t bytes, size_t alignment_hint, + bool exec) { + if (commit_memory(addr, bytes, exec)) { if (UseMPSS && alignment_hint > (size_t)vm_page_size()) { // If the large page size has been set and the VM // is using large pages, use the large page size @@ -3220,7 +3221,9 @@ return true; } -char* os::reserve_memory_special(size_t bytes, char* addr) { +char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { + // "exec" is passed in but not used. Creating the shared image for + // the code cache doesn't have an SHM_X executable permission to check. assert(UseLargePages && UseISM, "only for ISM large pages"); size_t size = bytes; diff -r cea947c8a988 -r a80d48f6fde1 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os/windows/vm/os_windows.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -2189,7 +2189,8 @@ if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) { addr = (address)((uintptr_t)addr & (~((uintptr_t)os::vm_page_size() - (uintptr_t)1))); - os::commit_memory( (char *)addr, thread->stack_base() - addr ); + os::commit_memory((char *)addr, thread->stack_base() - addr, + false ); return EXCEPTION_CONTINUE_EXECUTION; } else @@ -2565,8 +2566,7 @@ assert((size_t)addr % os::vm_allocation_granularity() == 0, "reserve alignment"); assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size"); - char* res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, - PAGE_EXECUTE_READWRITE); + char* res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE); assert(res == NULL || addr == NULL || addr == res, "Unexpected address from reserve."); return res; @@ -2595,7 +2595,7 @@ return true; } -char* os::reserve_memory_special(size_t bytes, char* addr) { +char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { if (UseLargePagesIndividualAllocation) { if (TracePageSizes && Verbose) { @@ -2618,7 +2618,7 @@ p_buf = (char *) VirtualAlloc(addr, size_of_reserve, // size of Reserve MEM_RESERVE, - PAGE_EXECUTE_READWRITE); + PAGE_READWRITE); // If reservation failed, return NULL if (p_buf == NULL) return NULL; @@ -2659,7 +2659,13 @@ p_new = (char *) VirtualAlloc(next_alloc_addr, bytes_to_rq, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, - PAGE_EXECUTE_READWRITE); + PAGE_READWRITE); + if (p_new != NULL && exec) { + DWORD oldprot; + // Windows doc says to use VirtualProtect to get execute permissions + VirtualProtect(next_alloc_addr, bytes_to_rq, + PAGE_EXECUTE_READWRITE, &oldprot); + } } if (p_new == NULL) { @@ -2688,10 +2694,12 @@ } else { // normal policy just allocate it all at once DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; - char * res = (char *)VirtualAlloc(NULL, - bytes, - flag, - PAGE_EXECUTE_READWRITE); + char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_READWRITE); + if (res != NULL && exec) { + DWORD oldprot; + // Windows doc says to use VirtualProtect to get execute permissions + VirtualProtect(res, bytes, PAGE_EXECUTE_READWRITE, &oldprot); + } return res; } } @@ -2703,7 +2711,7 @@ void os::print_statistics() { } -bool os::commit_memory(char* addr, size_t bytes) { +bool os::commit_memory(char* addr, size_t bytes, bool exec) { if (bytes == 0) { // Don't bother the OS with noops. return true; @@ -2712,11 +2720,19 @@ assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks"); // Don't attempt to print anything if the OS call fails. We're // probably low on resources, so the print itself may cause crashes. - return VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE) != NULL; + bool result = VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) != 0; + if (result != NULL && exec) { + DWORD oldprot; + // Windows doc says to use VirtualProtect to get execute permissions + return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot) != 0; + } else { + return result; + } } -bool os::commit_memory(char* addr, size_t size, size_t alignment_hint) { - return commit_memory(addr, size); +bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, + bool exec) { + return commit_memory(addr, size, exec); } bool os::uncommit_memory(char* addr, size_t bytes) { @@ -2750,7 +2766,7 @@ // Strange enough, but on Win32 one can change protection only for committed // memory, not a big deal anyway, as bytes less or equal than 64K - if (!is_committed && !commit_memory(addr, bytes)) { + if (!is_committed && !commit_memory(addr, bytes, prot == MEM_PROT_RWX)) { fatal("cannot commit protection page"); } // One cannot use os::guard_memory() here, as on Win32 guard page @@ -3248,10 +3264,10 @@ #endif if (!UseMembar) { - address mem_serialize_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_EXECUTE_READWRITE); + address mem_serialize_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_READWRITE); guarantee( mem_serialize_page != NULL, "Reserve Failed for memory serialize page"); - return_page = (address)VirtualAlloc(mem_serialize_page, os::vm_page_size(), MEM_COMMIT, PAGE_EXECUTE_READWRITE); + return_page = (address)VirtualAlloc(mem_serialize_page, os::vm_page_size(), MEM_COMMIT, PAGE_READWRITE); guarantee( return_page != NULL, "Commit Failed for memory serialize page"); os::set_memory_serialize_page( mem_serialize_page ); diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp --- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -29,13 +29,11 @@ static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint); static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong); static jint (*atomic_add_func) (jint, volatile jint*); - static void (*fence_func) (); static jint atomic_xchg_bootstrap (jint, volatile jint*); static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint); static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); static jint atomic_add_bootstrap (jint, volatile jint*); - static void fence_bootstrap (); static void setup_fpu() {} diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp --- a/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -44,11 +44,12 @@ inline void OrderAccess::fence() { if (os::is_MP()) { + // always use locked addl since mfence is sometimes expensive #ifdef AMD64 - __asm__ __volatile__ ("mfence":::"memory"); + __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory"); #else __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); -#endif // AMD64 +#endif } } diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp --- a/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -60,22 +60,10 @@ dummy = 0; } -#if defined(COMPILER2) || defined(_LP64) - inline void OrderAccess::fence() { _OrderAccess_fence(); } -#else // defined(COMPILER2) || defined(_LP64) - -inline void OrderAccess::fence() { - if (os::is_MP()) { - (*os::fence_func)(); - } -} - -#endif // defined(COMPILER2) || defined(_LP64) - #endif // _GNU_SOURCE inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp --- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -619,7 +619,6 @@ typedef jint cmpxchg_func_t (jint, volatile jint*, jint); typedef jlong cmpxchg_long_func_t(jlong, volatile jlong*, jlong); typedef jint add_func_t (jint, volatile jint*); -typedef void fence_func_t (); jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) { // try to use the stub: @@ -681,25 +680,10 @@ return (*dest) += add_value; } -void os::fence_bootstrap() { - // try to use the stub: - fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry()); - - if (func != NULL) { - os::fence_func = func; - (*func)(); - return; - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - // don't have to do anything for a single thread -} - xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; -fence_func_t* os::fence_func = os::fence_bootstrap; #endif // !_LP64 && !COMPILER2 diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp --- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -29,13 +29,11 @@ static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint); static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong); static jint (*atomic_add_func) (jint, volatile jint*); - static void (*fence_func) (); static jint atomic_xchg_bootstrap (jint, volatile jint*); static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint); static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); static jint atomic_add_bootstrap (jint, volatile jint*); - static void fence_bootstrap (); static void setup_fpu() {} diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp --- a/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -61,11 +61,8 @@ #endif // AMD64 } inline void _OrderAccess_fence() { -#ifdef AMD64 - __asm__ __volatile__ ("mfence":::"memory"); -#else + // Always use locked addl since mfence is sometimes expensive __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); -#endif // AMD64 } } diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp --- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -794,7 +794,6 @@ typedef jint cmpxchg_func_t (jint, volatile jint*, jint); typedef jlong cmpxchg_long_func_t(jlong, volatile jlong*, jlong); typedef jint add_func_t (jint, volatile jint*); -typedef void fence_func_t (); jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) { // try to use the stub: @@ -856,25 +855,10 @@ return (*dest) += add_value; } -void os::fence_bootstrap() { - // try to use the stub: - fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry()); - - if (func != NULL) { - os::fence_func = func; - (*func)(); - return; - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - // don't have to do anything for a single thread -} - xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; -fence_func_t* os::fence_func = os::fence_bootstrap; extern "C" _solaris_raw_setup_fpu(address ptr); void os::setup_fpu() { diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/solaris_x86/vm/os_solaris_x86.hpp --- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -32,13 +32,11 @@ static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint); static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong); static jint (*atomic_add_func) (jint, volatile jint*); - static void (*fence_func) (); static jint atomic_xchg_bootstrap (jint, volatile jint*); static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint); static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); static jint atomic_add_bootstrap (jint, volatile jint*); - static void fence_bootstrap (); static void setup_fpu(); #endif // AMD64 diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp --- a/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -46,7 +46,7 @@ inline void OrderAccess::fence() { #ifdef AMD64 - (*os::fence_func)(); + StubRoutines_fence(); #else if (os::is_MP()) { __asm { diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/windows_x86/vm/os_windows_x86.cpp --- a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -196,7 +196,6 @@ typedef jlong cmpxchg_long_func_t (jlong, volatile jlong*, jlong); typedef jint add_func_t (jint, volatile jint*); typedef intptr_t add_ptr_func_t (intptr_t, volatile intptr_t*); -typedef void fence_func_t (); #ifdef AMD64 @@ -292,27 +291,11 @@ return (*dest) += add_value; } -void os::fence_bootstrap() { - // try to use the stub: - fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry()); - - if (func != NULL) { - os::fence_func = func; - (*func)(); - return; - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - // don't have to do anything for a single thread -} - - xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; xchg_ptr_func_t* os::atomic_xchg_ptr_func = os::atomic_xchg_ptr_bootstrap; cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; add_ptr_func_t* os::atomic_add_ptr_func = os::atomic_add_ptr_bootstrap; -fence_func_t* os::fence_func = os::fence_bootstrap; #endif // AMD64 diff -r cea947c8a988 -r a80d48f6fde1 src/os_cpu/windows_x86/vm/os_windows_x86.hpp --- a/src/os_cpu/windows_x86/vm/os_windows_x86.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/os_cpu/windows_x86/vm/os_windows_x86.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -35,9 +35,6 @@ static jint (*atomic_add_func) (jint, volatile jint*); static intptr_t (*atomic_add_ptr_func) (intptr_t, volatile intptr_t*); - static void (*fence_func) (); - - static jint atomic_xchg_bootstrap (jint, volatile jint*); static intptr_t atomic_xchg_ptr_bootstrap (intptr_t, volatile intptr_t*); @@ -53,8 +50,6 @@ #ifdef AMD64 static jint atomic_add_bootstrap (jint, volatile jint*); static intptr_t atomic_add_ptr_bootstrap (intptr_t, volatile intptr_t*); - - static void fence_bootstrap (); #endif // AMD64 static void setup_fpu(); diff -r cea947c8a988 -r a80d48f6fde1 src/share/tools/MakeDeps/WinGammaPlatformVC7.java --- a/src/share/tools/MakeDeps/WinGammaPlatformVC7.java Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/tools/MakeDeps/WinGammaPlatformVC7.java Thu Apr 02 05:22:02 2009 -0700 @@ -27,6 +27,8 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform { + String projectVersion() {return "7.10";}; + public void writeProjectFile(String projectFileName, String projectName, Vector allConfigs) throws IOException { System.out.println(); @@ -40,7 +42,7 @@ "VisualStudioProject", new String[] { "ProjectType", "Visual C++", - "Version", "7.10", + "Version", projectVersion(), "Name", projectName, "ProjectGUID", "{8822CB5C-1C41-41C2-8493-9F6E1994338B}", "SccProjectName", "", @@ -417,7 +419,9 @@ new String[] { "Name", "VCPreLinkEventTool", "Description", BuildConfig.getFieldString(null, "PrelinkDescription"), - "CommandLine", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace('\t', '\n')) + //Caution: String.replace(String,String) is available from JDK5 onwards only + "CommandLine", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace + ("\t", " ")) } ); @@ -542,25 +546,41 @@ } class CompilerInterfaceVC7 extends CompilerInterface { - Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir) { - Vector rv = new Vector(); + void getBaseCompilerFlags_common(Vector defines, Vector includes, String outDir,Vector rv) { // advanced M$ IDE (2003) can only recognize name if it's first or // second attribute in the tag - go guess addAttr(rv, "Name", "VCCLCompilerTool"); addAttr(rv, "AdditionalIncludeDirectories", Util.join(",", includes)); - addAttr(rv, "PreprocessorDefinitions", Util.join(";", defines).replace("\"",""")); - addAttr(rv, "UsePrecompiledHeader", "3"); - addAttr(rv, "PrecompiledHeaderThrough", "incls"+Util.sep+"_precompiled.incl"); + addAttr(rv, "PreprocessorDefinitions", + Util.join(";", defines).replace("\"",""")); + addAttr(rv, "PrecompiledHeaderThrough", + "incls"+Util.sep+"_precompiled.incl"); addAttr(rv, "PrecompiledHeaderFile", outDir+Util.sep+"vm.pch"); addAttr(rv, "AssemblerListingLocation", outDir); addAttr(rv, "ObjectFile", outDir+Util.sep); addAttr(rv, "ProgramDataBaseFileName", outDir+Util.sep+"vm.pdb"); + // Set /nologo optin addAttr(rv, "SuppressStartupBanner", "TRUE"); + // Surpass the default /Tc or /Tp. 0 is compileAsDefault addAttr(rv, "CompileAs", "0"); + // Set /W3 option. 3 is warningLevel_3 addAttr(rv, "WarningLevel", "3"); + // Set /WX option, addAttr(rv, "WarnAsError", "TRUE"); + // Set /GS option addAttr(rv, "BufferSecurityCheck", "FALSE"); + // Set /Zi option. 3 is debugEnabled + addAttr(rv, "DebugInformationFormat", "3"); + } + Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir) { + Vector rv = new Vector(); + + getBaseCompilerFlags_common(defines,includes, outDir, rv); + // Set /Yu option. 3 is pchUseUsingSpecific + // Note: Starting VC8 pchUseUsingSpecific is 2 !!! + addAttr(rv, "UsePrecompiledHeader", "3"); + // Set /EHsc- option addAttr(rv, "ExceptionHandling", "FALSE"); return rv; @@ -579,27 +599,39 @@ "/export:jio_vsnprintf "); addAttr(rv, "AdditionalDependencies", "Wsock32.lib winmm.lib"); addAttr(rv, "OutputFile", outDll); + // Set /INCREMENTAL option. 1 is linkIncrementalNo addAttr(rv, "LinkIncremental", "1"); addAttr(rv, "SuppressStartupBanner", "TRUE"); addAttr(rv, "ModuleDefinitionFile", outDir+Util.sep+"vm.def"); addAttr(rv, "ProgramDatabaseFile", outDir+Util.sep+"vm.pdb"); + // Set /SUBSYSTEM option. 2 is subSystemWindows 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"); return rv; } + void getDebugCompilerFlags_common(String opt,Vector rv) { + + // Set /On option + addAttr(rv, "Optimization", opt); + // Set /FR option. 1 is brAllInfo + addAttr(rv, "BrowseInformation", "1"); + addAttr(rv, "BrowseInformationFile", "$(IntDir)" + Util.sep); + // Set /MD option. 2 is rtMultiThreadedDLL + addAttr(rv, "RuntimeLibrary", "2"); + // Set /Oy- option + addAttr(rv, "OmitFramePointers", "FALSE"); + + } + Vector getDebugCompilerFlags(String opt) { Vector rv = new Vector(); - addAttr(rv, "Optimization", opt); - addAttr(rv, "OptimizeForProcessor", "1"); - addAttr(rv, "DebugInformationFormat", "3"); - addAttr(rv, "RuntimeLibrary", "2"); - addAttr(rv, "BrowseInformation", "1"); - addAttr(rv, "BrowseInformationFile", "$(IntDir)" + Util.sep); + getDebugCompilerFlags_common(opt,rv); return rv; } @@ -607,18 +639,29 @@ Vector getDebugLinkerFlags() { Vector rv = new Vector(); - addAttr(rv, "GenerateDebugInformation", "TRUE"); + addAttr(rv, "GenerateDebugInformation", "TRUE"); // == /DEBUG option return rv; } + void getProductCompilerFlags_common(Vector rv) { + // Set /O2 option. 2 is optimizeMaxSpeed + addAttr(rv, "Optimization", "2"); + // Set /Oy- option + addAttr(rv, "OmitFramePointers", "FALSE"); + } + Vector getProductCompilerFlags() { Vector rv = new Vector(); - addAttr(rv, "Optimization", "2"); + getProductCompilerFlags_common(rv); + // Set /Ob option. 1 is expandOnlyInline addAttr(rv, "InlineFunctionExpansion", "1"); + // Set /GF option. addAttr(rv, "StringPooling", "TRUE"); + // Set /MD option. 2 is rtMultiThreadedDLL addAttr(rv, "RuntimeLibrary", "2"); + // Set /Gy option addAttr(rv, "EnableFunctionLevelLinking", "TRUE"); return rv; @@ -627,7 +670,9 @@ Vector getProductLinkerFlags() { Vector rv = new Vector(); + // Set /OPT:REF option. 2 is optReferences addAttr(rv, "OptimizeReferences", "2"); + // Set /OPT:optFolding option. 2 is optFolding addAttr(rv, "EnableCOMDATFolding", "2"); return rv; diff -r cea947c8a988 -r a80d48f6fde1 src/share/tools/MakeDeps/WinGammaPlatformVC8.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/MakeDeps/WinGammaPlatformVC8.java Thu Apr 02 05:22:02 2009 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +import java.io.*; +import java.util.*; + +public class WinGammaPlatformVC8 extends WinGammaPlatformVC7 { + + String projectVersion() {return "8.00";}; + +} + +class CompilerInterfaceVC8 extends CompilerInterfaceVC7 { + + Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir) { + Vector rv = new Vector(); + + getBaseCompilerFlags_common(defines,includes, outDir, rv); + // Set /Yu option. 2 is pchUseUsingSpecific + addAttr(rv, "UsePrecompiledHeader", "2"); + // Set /EHsc- option. 0 is cppExceptionHandlingNo + addAttr(rv, "ExceptionHandling", "0"); + + return rv; + } + + + Vector getDebugCompilerFlags(String opt) { + Vector rv = new Vector(); + + getDebugCompilerFlags_common(opt,rv); + + return rv; + } + + Vector getProductCompilerFlags() { + Vector rv = new Vector(); + + getProductCompilerFlags_common(rv); + + return rv; + } + + +} diff -r cea947c8a988 -r a80d48f6fde1 src/share/tools/MakeDeps/WinGammaPlatformVC9.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/MakeDeps/WinGammaPlatformVC9.java Thu Apr 02 05:22:02 2009 -0700 @@ -0,0 +1,35 @@ +/* + * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +import java.io.*; +import java.util.*; + +public class WinGammaPlatformVC9 extends WinGammaPlatformVC8 { + + String projectVersion() {return "9.00";}; + +} + +class CompilerInterfaceVC9 extends CompilerInterfaceVC8 { +} diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/asm/assembler.hpp --- a/src/share/vm/asm/assembler.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/asm/assembler.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -143,15 +143,15 @@ // A union type for code which has to assemble both constant and // non-constant operands, when the distinction cannot be made // statically. -class RegisterConstant VALUE_OBJ_CLASS_SPEC { +class RegisterOrConstant VALUE_OBJ_CLASS_SPEC { private: Register _r; intptr_t _c; public: - RegisterConstant(): _r(noreg), _c(0) {} - RegisterConstant(Register r): _r(r), _c(0) {} - RegisterConstant(intptr_t c): _r(noreg), _c(c) {} + RegisterOrConstant(): _r(noreg), _c(0) {} + RegisterOrConstant(Register r): _r(r), _c(0) {} + RegisterOrConstant(intptr_t c): _r(noreg), _c(c) {} Register as_register() const { assert(is_register(),""); return _r; } intptr_t as_constant() const { assert(is_constant(),""); return _c; } @@ -310,13 +310,13 @@ // offsets in code which must be generated before the object class is loaded. // Field offsets are never zero, since an object's header (mark word) // is located at offset zero. - RegisterConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) { - return delayed_value(delayed_value_addr(value_fn), tmp, offset); + RegisterOrConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) { + return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset); } - RegisterConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) { - return delayed_value(delayed_value_addr(value_fn), tmp, offset); + RegisterOrConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) { + return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset); } - virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset) = 0; + virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset) = 0; // Last overloading is platform-dependent; look in assembler_.cpp. static intptr_t* delayed_value_addr(int(*constant_fn)()); static intptr_t* delayed_value_addr(address(*constant_fn)()); diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/ci/ciTypeFlow.cpp --- a/src/share/vm/ci/ciTypeFlow.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/ci/ciTypeFlow.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -2237,7 +2237,6 @@ for (SuccIter iter(tail); !iter.done(); iter.next()) { if (iter.succ() == head) { iter.set_succ(clone); - break; } } flow_block(tail, temp_vector, temp_set); diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/classfile/classFileParser.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -2747,9 +2747,10 @@ super_klass(), methods(), access_flags, - class_loader(), - class_name(), - local_interfaces()); + class_loader, + class_name, + local_interfaces(), + CHECK_(nullHandle)); // Size of Java itable (in words) itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces); @@ -3229,7 +3230,7 @@ // print out the superclass. const char * from = Klass::cast(this_klass())->external_name(); if (this_klass->java_super() != NULL) { - tty->print("RESOLVE %s %s\n", from, instanceKlass::cast(this_klass->java_super())->external_name()); + tty->print("RESOLVE %s %s (super)\n", from, instanceKlass::cast(this_klass->java_super())->external_name()); } // print out each of the interface classes referred to by this class. objArrayHandle local_interfaces(THREAD, this_klass->local_interfaces()); @@ -3239,7 +3240,7 @@ klassOop k = klassOop(local_interfaces->obj_at(i)); instanceKlass* to_class = instanceKlass::cast(k); const char * to = to_class->external_name(); - tty->print("RESOLVE %s %s\n", from, to); + tty->print("RESOLVE %s %s (interface)\n", from, to); } } } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -239,22 +239,20 @@ typeArrayOop value = java_lang_String::value(obj); int offset = java_lang_String::offset(obj); int length = java_lang_String::length(obj); - - ResourceMark rm(THREAD); - symbolHandle result; - - if (length > 0) { - int utf8_length = UNICODE::utf8_length(value->char_at_addr(offset), length); - char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); - UNICODE::convert_to_utf8(value->char_at_addr(offset), length, chars); - // Allocate the symbol - result = oopFactory::new_symbol_handle(chars, utf8_length, CHECK_(symbolHandle())); - } else { - result = oopFactory::new_symbol_handle("", 0, CHECK_(symbolHandle())); - } - return result; + jchar* base = value->char_at_addr(offset); + symbolOop sym = SymbolTable::lookup_unicode(base, length, THREAD); + return symbolHandle(THREAD, sym); } +symbolOop java_lang_String::as_symbol_or_null(oop java_string) { + typeArrayOop value = java_lang_String::value(java_string); + int offset = java_lang_String::offset(java_string); + int length = java_lang_String::length(java_string); + jchar* base = value->char_at_addr(offset); + return SymbolTable::probe_unicode(base, length); +} + + int java_lang_String::utf8_length(oop java_string) { typeArrayOop value = java_lang_String::value(java_string); int offset = java_lang_String::offset(java_string); @@ -385,6 +383,48 @@ } +void java_lang_Class::print_signature(oop java_class, outputStream* st) { + assert(java_lang_Class::is_instance(java_class), "must be a Class object"); + symbolOop name = NULL; + bool is_instance = false; + if (is_primitive(java_class)) { + name = vmSymbols::type_signature(primitive_type(java_class)); + } else { + klassOop k = as_klassOop(java_class); + is_instance = Klass::cast(k)->oop_is_instance(); + name = Klass::cast(k)->name(); + } + if (name == NULL) { + st->print(""); + return; + } + if (is_instance) st->print("L"); + st->write((char*) name->base(), (int) name->utf8_length()); + if (is_instance) st->print(";"); +} + +symbolOop java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, TRAPS) { + assert(java_lang_Class::is_instance(java_class), "must be a Class object"); + symbolOop name = NULL; + if (is_primitive(java_class)) { + return vmSymbols::type_signature(primitive_type(java_class)); + } else { + klassOop k = as_klassOop(java_class); + if (!Klass::cast(k)->oop_is_instance()) { + return Klass::cast(k)->name(); + } else { + ResourceMark rm; + const char* sigstr = Klass::cast(k)->signature_name(); + int siglen = (int) strlen(sigstr); + if (!intern_if_not_found) + return SymbolTable::probe(sigstr, siglen); + else + return oopFactory::new_symbol(sigstr, siglen, THREAD); + } + } +} + + klassOop java_lang_Class::array_klass(oop java_class) { klassOop k = klassOop(java_class->obj_field(array_klass_offset)); assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_javaArray(), "should be array klass"); @@ -412,6 +452,8 @@ bool java_lang_Class::is_primitive(oop java_class) { + // should assert: + //assert(java_lang_Class::is_instance(java_class), "must be a Class object"); klassOop k = klassOop(java_class->obj_field(klass_offset)); return k == NULL; } @@ -431,6 +473,19 @@ return type; } +BasicType java_lang_Class::as_BasicType(oop java_class, klassOop* reference_klass) { + assert(java_lang_Class::is_instance(java_class), "must be a Class object"); + if (is_primitive(java_class)) { + if (reference_klass != NULL) + (*reference_klass) = NULL; + return primitive_type(java_class); + } else { + if (reference_klass != NULL) + (*reference_klass) = as_klassOop(java_class); + return T_OBJECT; + } +} + oop java_lang_Class::primitive_mirror(BasicType t) { oop mirror = Universe::java_mirror(t); @@ -1988,6 +2043,21 @@ } +void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream* st) { + switch (type) { + case T_BOOLEAN: st->print("%s", value->z ? "true" : "false"); break; + case T_CHAR: st->print("%d", value->c); break; + case T_BYTE: st->print("%d", value->b); break; + case T_SHORT: st->print("%d", value->s); break; + case T_INT: st->print("%d", value->i); break; + case T_LONG: st->print(INT64_FORMAT, value->j); break; + case T_FLOAT: st->print("%f", value->f); break; + case T_DOUBLE: st->print("%lf", value->d); break; + default: st->print("type %d?", type); break; + } +} + + // Support for java_lang_ref_Reference oop java_lang_ref_Reference::pending_list_lock() { instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass()); diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -107,6 +107,7 @@ // Conversion static symbolHandle as_symbol(Handle java_string, TRAPS); + static symbolOop as_symbol_or_null(oop java_string); // Testers static bool is_instance(oop obj) { @@ -149,6 +150,9 @@ static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS); // Conversion static klassOop as_klassOop(oop java_class); + static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL); + static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS); + static void print_signature(oop java_class, outputStream *st); // Testing static bool is_instance(oop obj) { return obj != NULL && obj->klass() == SystemDictionary::class_klass(); @@ -668,6 +672,8 @@ static BasicType basic_type(oop box); static bool is_instance(oop box) { return basic_type(box) != T_ILLEGAL; } static bool is_instance(oop box, BasicType type) { return basic_type(box) == type; } + static void print(oop box, outputStream* st) { jvalue value; print(get_value(box, &value), &value, st); } + static void print(BasicType type, jvalue* value, outputStream* st); static int value_offset_in_bytes(BasicType type) { return ( type == T_LONG || type == T_DOUBLE ) ? long_value_offset : diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/classfile/loaderConstraints.hpp --- a/src/share/vm/classfile/loaderConstraints.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/classfile/loaderConstraints.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,8 +60,10 @@ bool add_entry(symbolHandle name, klassOop klass1, Handle loader1, klassOop klass2, Handle loader2); - void check_signature_loaders(symbolHandle signature, Handle loader1, - Handle loader2, bool is_method, TRAPS); + // Note: The main entry point for this module is via SystemDictionary. + // SystemDictionary::check_signature_loaders(symbolHandle signature, + // Handle loader1, Handle loader2, + // bool is_method, TRAPS) klassOop find_constrained_klass(symbolHandle name, Handle loader); klassOop find_constrained_elem_klass(symbolHandle name, symbolHandle elem_name, diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/classfile/symbolTable.cpp --- a/src/share/vm/classfile/symbolTable.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/classfile/symbolTable.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,6 +109,40 @@ return the_table()->lookup(index, name, len, hash); } +// Suggestion: Push unicode-based lookup all the way into the hashing +// and probing logic, so there is no need for convert_to_utf8 until +// an actual new symbolOop is created. +symbolOop SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { + int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); + char stack_buf[128]; + if (utf8_length < (int) sizeof(stack_buf)) { + char* chars = stack_buf; + UNICODE::convert_to_utf8(name, utf16_length, chars); + return lookup(chars, utf8_length, THREAD); + } else { + ResourceMark rm(THREAD); + char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);; + UNICODE::convert_to_utf8(name, utf16_length, chars); + return lookup(chars, utf8_length, THREAD); + } +} + +symbolOop SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, + unsigned int& hash) { + int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); + char stack_buf[128]; + if (utf8_length < (int) sizeof(stack_buf)) { + char* chars = stack_buf; + UNICODE::convert_to_utf8(name, utf16_length, chars); + return lookup_only(chars, utf8_length, hash); + } else { + ResourceMark rm; + char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);; + UNICODE::convert_to_utf8(name, utf16_length, chars); + return lookup_only(chars, utf8_length, hash); + } +} + void SymbolTable::add(constantPoolHandle cp, int names_count, const char** names, int* lengths, int* cp_indices, unsigned int* hashValues, TRAPS) { @@ -126,15 +160,6 @@ } } -// Needed for preloading classes in signatures when compiling. - -symbolOop SymbolTable::probe(const char* name, int len) { - unsigned int hashValue = hash_symbol(name, len); - int index = the_table()->hash_to_index(hashValue); - return the_table()->lookup(index, name, len, hashValue); -} - - symbolOop SymbolTable::basic_add(int index, u1 *name, int len, unsigned int hashValue, TRAPS) { assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/classfile/symbolTable.hpp --- a/src/share/vm/classfile/symbolTable.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/classfile/symbolTable.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,6 +91,10 @@ // Only copy to C string to be added if lookup failed. static symbolOop lookup(symbolHandle sym, int begin, int end, TRAPS); + // jchar (utf16) version of lookups + static symbolOop lookup_unicode(const jchar* name, int len, TRAPS); + static symbolOop lookup_only_unicode(const jchar* name, int len, unsigned int& hash); + static void add(constantPoolHandle cp, int names_count, const char** names, int* lengths, int* cp_indices, unsigned int* hashValues, TRAPS); @@ -112,7 +116,14 @@ // Needed for preloading classes in signatures when compiling. // Returns the symbol is already present in symbol table, otherwise // NULL. NO ALLOCATION IS GUARANTEED! - static symbolOop probe(const char* name, int len); + static symbolOop probe(const char* name, int len) { + unsigned int ignore_hash; + return lookup_only(name, len, ignore_hash); + } + static symbolOop probe_unicode(const jchar* name, int len) { + unsigned int ignore_hash; + return lookup_only_unicode(name, len, ignore_hash); + } // Histogram static void print_histogram() PRODUCT_RETURN; diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1964,6 +1964,13 @@ return T_OBJECT; } +KlassHandle SystemDictionaryHandles::box_klass(BasicType t) { + if (t >= T_BOOLEAN && t <= T_VOID) + return KlassHandle(&SystemDictionary::_box_klasses[t], true); + else + return KlassHandle(); +} + // Constraints on class loaders. The details of the algorithm can be // found in the OOPSLA'98 paper "Dynamic Class Loading in the Java // Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is @@ -2174,11 +2181,56 @@ } +// Signature constraints ensure that callers and callees agree about +// the meaning of type names in their signatures. This routine is the +// intake for constraints. It collects them from several places: +// +// * LinkResolver::resolve_method (if check_access is true) requires +// that the resolving class (the caller) and the defining class of +// the resolved method (the callee) agree on each type in the +// method's signature. +// +// * LinkResolver::resolve_interface_method performs exactly the same +// checks. +// +// * LinkResolver::resolve_field requires that the constant pool +// attempting to link to a field agree with the field's defining +// class about the type of the field signature. +// +// * klassVtable::initialize_vtable requires that, when a class +// overrides a vtable entry allocated by a superclass, that the +// overriding method (i.e., the callee) agree with the superclass +// on each type in the method's signature. +// +// * klassItable::initialize_itable requires that, when a class fills +// in its itables, for each non-abstract method installed in an +// itable, the method (i.e., the callee) agree with the interface +// on each type in the method's signature. +// +// All those methods have a boolean (check_access, checkconstraints) +// which turns off the checks. This is used from specialized contexts +// such as bootstrapping, dumping, and debugging. +// +// No direct constraint is placed between the class and its +// supertypes. Constraints are only placed along linked relations +// between callers and callees. When a method overrides or implements +// an abstract method in a supertype (superclass or interface), the +// constraints are placed as if the supertype were the caller to the +// overriding method. (This works well, since callers to the +// supertype have already established agreement between themselves and +// the supertype.) As a result of all this, a class can disagree with +// its supertype about the meaning of a type name, as long as that +// class neither calls a relevant method of the supertype, nor is +// called (perhaps via an override) from the supertype. +// +// +// SystemDictionary::check_signature_loaders(sig, l1, l2) +// // Make sure all class components (including arrays) in the given // signature will be resolved to the same class in both loaders. // Returns the name of the type that failed a loader constraint check, or // NULL if no constraint failed. The returned C string needs cleaning up -// with a ResourceMark in the caller +// with a ResourceMark in the caller. No exception except OOME is thrown. char* SystemDictionary::check_signature_loaders(symbolHandle signature, Handle loader1, Handle loader2, bool is_method, TRAPS) { diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -161,6 +161,7 @@ class SystemDictionary : AllStatic { friend class VMStructs; friend class CompactingPermGenGen; + friend class SystemDictionaryHandles; NOT_PRODUCT(friend class instanceKlassKlass;) public: @@ -595,3 +596,18 @@ static bool _has_loadClassInternal; static bool _has_checkPackageAccess; }; + +// Cf. vmSymbols vs. vmSymbolHandles +class SystemDictionaryHandles : AllStatic { +public: + #define WK_KLASS_HANDLE_DECLARE(name, ignore_symbol, option) \ + static KlassHandle name() { \ + SystemDictionary::name(); \ + klassOop* loc = &SystemDictionary::_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \ + return KlassHandle(loc, true); \ + } + WK_KLASSES_DO(WK_KLASS_HANDLE_DECLARE); + #undef WK_KLASS_HANDLE_DECLARE + + static KlassHandle box_klass(BasicType t); +}; diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -49,6 +49,8 @@ template(java_lang_Object, "java/lang/Object") \ template(java_lang_Class, "java/lang/Class") \ template(java_lang_String, "java/lang/String") \ + template(java_lang_StringValue, "java/lang/StringValue") \ + template(java_lang_StringCache, "java/lang/StringValue$StringCache") \ template(java_lang_Thread, "java/lang/Thread") \ template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \ template(java_lang_Cloneable, "java/lang/Cloneable") \ @@ -285,6 +287,7 @@ template(frontCacheEnabled_name, "frontCacheEnabled") \ template(stringCacheEnabled_name, "stringCacheEnabled") \ template(bitCount_name, "bitCount") \ + template(profile_name, "profile") \ \ /* non-intrinsic name/signature pairs: */ \ template(register_method_name, "register") \ @@ -378,7 +381,7 @@ template(unknown_class_name, "") \ \ /* used to identify class loaders handling parallel class loading */ \ - template(parallelCapable_name, "parallelLockMap;") \ + template(parallelCapable_name, "parallelLockMap") \ \ /* JVM monitoring and management support */ \ template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \ diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -825,6 +825,7 @@ if (young_gen()->is_in_reserved(addr)) { assert(young_gen()->is_in(addr), "addr should be in allocated part of young gen"); + if (Debugging) return NULL; // called from find() in debug.cpp Unimplemented(); } else if (old_gen()->is_in_reserved(addr)) { assert(old_gen()->is_in(addr), diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/includeDB_core --- a/src/share/vm/includeDB_core Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/includeDB_core Thu Apr 02 05:22:02 2009 -0700 @@ -3154,6 +3154,8 @@ oopsHierarchy.cpp thread_.inline.hpp orderAccess.cpp orderAccess.hpp +orderAccess.cpp stubRoutines.hpp +orderAccess.cpp thread.hpp orderAccess.hpp allocation.hpp orderAccess.hpp os.hpp diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/interpreter/invocationCounter.cpp --- a/src/share/vm/interpreter/invocationCounter.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/interpreter/invocationCounter.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -47,6 +47,8 @@ // executed many more times before re-entering the VM. int old_count = count(); int new_count = MIN2(old_count, (int) (CompileThreshold / 2)); + // prevent from going to zero, to distinguish from never-executed methods + if (new_count == 0) new_count = 1; if (old_count != new_count) set(state(), new_count); } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/memory/heap.cpp --- a/src/share/vm/memory/heap.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/memory/heap.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -112,7 +112,7 @@ const size_t rs_align = page_size == (size_t) os::vm_page_size() ? 0 : MAX2(page_size, granularity); - ReservedSpace rs(r_size, rs_align, rs_align > 0); + ReservedCodeSpace rs(r_size, rs_align, rs_align > 0); os::trace_page_sizes("code heap", committed_size, reserved_size, page_size, rs.base(), rs.size()); if (!_memory.initialize(rs, c_size)) { diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1813,6 +1813,8 @@ oop class_loader2, symbolOop class_name2) { if (class_loader1 != class_loader2) { return false; + } else if (class_name1 == class_name2) { + return true; // skip painful bytewise comparison } else { ResourceMark rm; @@ -1859,6 +1861,75 @@ } } +// Returns true iff super_method can be overridden by a method in targetclassname +// See JSL 3rd edition 8.4.6.1 +// Assumes name-signature match +// "this" is instanceKlass of super_method which must exist +// note that the instanceKlass of the method in the targetclassname has not always been created yet +bool instanceKlass::is_override(methodHandle super_method, Handle targetclassloader, symbolHandle targetclassname, TRAPS) { + // Private methods can not be overridden + if (super_method->is_private()) { + return false; + } + // If super method is accessible, then override + if ((super_method->is_protected()) || + (super_method->is_public())) { + return true; + } + // Package-private methods are not inherited outside of package + assert(super_method->is_package_private(), "must be package private"); + return(is_same_class_package(targetclassloader(), targetclassname())); +} + +/* defined for now in jvm.cpp, for historical reasons *-- +klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle self, + symbolOop& simple_name_result, TRAPS) { + ... +} +*/ + +// tell if two classes have the same enclosing class (at package level) +bool instanceKlass::is_same_package_member_impl(instanceKlassHandle class1, + klassOop class2_oop, TRAPS) { + if (class2_oop == class1->as_klassOop()) return true; + if (!Klass::cast(class2_oop)->oop_is_instance()) return false; + instanceKlassHandle class2(THREAD, class2_oop); + + // must be in same package before we try anything else + if (!class1->is_same_class_package(class2->class_loader(), class2->name())) + return false; + + // As long as there is an outer1.getEnclosingClass, + // shift the search outward. + instanceKlassHandle outer1 = class1; + for (;;) { + // As we walk along, look for equalities between outer1 and class2. + // Eventually, the walks will terminate as outer1 stops + // at the top-level class around the original class. + symbolOop ignore_name; + klassOop next = outer1->compute_enclosing_class(ignore_name, CHECK_false); + if (next == NULL) break; + if (next == class2()) return true; + outer1 = instanceKlassHandle(THREAD, next); + } + + // Now do the same for class2. + instanceKlassHandle outer2 = class2; + for (;;) { + symbolOop ignore_name; + klassOop next = outer2->compute_enclosing_class(ignore_name, CHECK_false); + if (next == NULL) break; + // Might as well check the new outer against all available values. + if (next == class1()) return true; + if (next == outer1()) return true; + outer2 = instanceKlassHandle(THREAD, next); + } + + // If by this point we have not found an equality between the + // two classes, we know they are in separate package members. + return false; +} + jint instanceKlass::compute_modifier_flags(TRAPS) const { klassOop k = as_klassOop(); @@ -1996,9 +2067,11 @@ // Printing +#define BULLET " - " + void FieldPrinter::do_field(fieldDescriptor* fd) { - if (fd->is_static() == (_obj == NULL)) { - _st->print(" - "); + _st->print(BULLET); + if (fd->is_static() || (_obj == NULL)) { fd->print_on(_st); _st->cr(); } else { @@ -2019,7 +2092,7 @@ value->is_typeArray() && offset <= (juint) value->length() && offset + length <= (juint) value->length()) { - st->print("string: "); + st->print(BULLET"string: "); Handle h_obj(obj); java_lang_String::print(h_obj, st); st->cr(); @@ -2027,23 +2100,26 @@ } } - st->print_cr("fields:"); + st->print_cr(BULLET"---- fields (total size %d words):", oop_size(obj)); FieldPrinter print_nonstatic_field(st, obj); do_nonstatic_fields(&print_nonstatic_field); if (as_klassOop() == SystemDictionary::class_klass()) { + st->print(BULLET"signature: "); + java_lang_Class::print_signature(obj, st); + st->cr(); klassOop mirrored_klass = java_lang_Class::as_klassOop(obj); - st->print(" - fake entry for mirror: "); + st->print(BULLET"fake entry for mirror: "); mirrored_klass->print_value_on(st); st->cr(); - st->print(" - fake entry resolved_constructor: "); + st->print(BULLET"fake entry resolved_constructor: "); methodOop ctor = java_lang_Class::resolved_constructor(obj); ctor->print_value_on(st); klassOop array_klass = java_lang_Class::array_klass(obj); - st->print(" - fake entry for array: "); + st->cr(); + st->print(BULLET"fake entry for array: "); array_klass->print_value_on(st); st->cr(); - st->cr(); } } @@ -2051,6 +2127,28 @@ st->print("a "); name()->print_value_on(st); obj->print_address_on(st); + if (as_klassOop() == SystemDictionary::string_klass() + && java_lang_String::value(obj) != NULL) { + ResourceMark rm; + int len = java_lang_String::length(obj); + int plen = (len < 24 ? len : 12); + char* str = java_lang_String::as_utf8_string(obj, 0, plen); + st->print(" = \"%s\"", str); + if (len > plen) + st->print("...[%d]", len); + } else if (as_klassOop() == SystemDictionary::class_klass()) { + klassOop k = java_lang_Class::as_klassOop(obj); + st->print(" = "); + if (k != NULL) { + k->print_value_on(st); + } else { + const char* tname = type2name(java_lang_Class::primitive_type(obj)); + st->print("%s", tname ? tname : "type?"); + } + } else if (java_lang_boxing_object::is_instance(obj)) { + st->print(" = "); + java_lang_boxing_object::print(obj, st); + } } #endif // ndef PRODUCT diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/oops/instanceKlass.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -303,11 +303,30 @@ inner_class_next_offset = 4 }; + // method override check + bool is_override(methodHandle super_method, Handle targetclassloader, symbolHandle targetclassname, TRAPS); + // package bool is_same_class_package(klassOop class2); bool is_same_class_package(oop classloader2, symbolOop classname2); static bool is_same_class_package(oop class_loader1, symbolOop class_name1, oop class_loader2, symbolOop class_name2); + // find an enclosing class (defined where original code was, in jvm.cpp!) + klassOop compute_enclosing_class(symbolOop& simple_name_result, TRAPS) { + instanceKlassHandle self(THREAD, this->as_klassOop()); + return compute_enclosing_class_impl(self, simple_name_result, THREAD); + } + static klassOop compute_enclosing_class_impl(instanceKlassHandle self, + symbolOop& simple_name_result, TRAPS); + + // tell if two classes have the same enclosing class (at package level) + bool is_same_package_member(klassOop class2, TRAPS) { + instanceKlassHandle self(THREAD, this->as_klassOop()); + return is_same_package_member_impl(self, class2, THREAD); + } + static bool is_same_package_member_impl(instanceKlassHandle self, + klassOop class2, TRAPS); + // initialization state bool is_loaded() const { return _init_state >= loaded; } bool is_linked() const { return _init_state >= linked; } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/oops/instanceKlassKlass.cpp --- a/src/share/vm/oops/instanceKlassKlass.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/oops/instanceKlassKlass.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -487,6 +487,8 @@ // Printing +#define BULLET " - " + static const char* state_names[] = { "unparseable_by_gc", "allocated", "loaded", "linked", "being_initialized", "fully_initialized", "initialization_error" }; @@ -497,13 +499,13 @@ instanceKlass* ik = instanceKlass::cast(klassOop(obj)); klassKlass::oop_print_on(obj, st); - st->print(" - instance size: %d", ik->size_helper()); st->cr(); - st->print(" - klass size: %d", ik->object_size()); st->cr(); - st->print(" - access: "); ik->access_flags().print_on(st); st->cr(); - st->print(" - state: "); st->print_cr(state_names[ik->_init_state]); - st->print(" - name: "); ik->name()->print_value_on(st); st->cr(); - st->print(" - super: "); ik->super()->print_value_on(st); st->cr(); - st->print(" - sub: "); + st->print(BULLET"instance size: %d", ik->size_helper()); st->cr(); + st->print(BULLET"klass size: %d", ik->object_size()); st->cr(); + st->print(BULLET"access: "); ik->access_flags().print_on(st); st->cr(); + st->print(BULLET"state: "); st->print_cr(state_names[ik->_init_state]); + st->print(BULLET"name: "); ik->name()->print_value_on(st); st->cr(); + st->print(BULLET"super: "); ik->super()->print_value_on(st); st->cr(); + st->print(BULLET"sub: "); Klass* sub = ik->subklass(); int n; for (n = 0; sub != NULL; n++, sub = sub->next_sibling()) { @@ -516,12 +518,12 @@ st->cr(); if (ik->is_interface()) { - st->print_cr(" - nof implementors: %d", ik->nof_implementors()); + st->print_cr(BULLET"nof implementors: %d", ik->nof_implementors()); int print_impl = 0; for (int i = 0; i < instanceKlass::implementors_limit; i++) { if (ik->implementor(i) != NULL) { if (++print_impl == 1) - st->print_cr(" - implementor: "); + st->print_cr(BULLET"implementor: "); st->print(" "); ik->implementor(i)->print_value_on(st); } @@ -529,34 +531,33 @@ if (print_impl > 0) st->cr(); } - st->print(" - arrays: "); ik->array_klasses()->print_value_on(st); st->cr(); - st->print(" - methods: "); ik->methods()->print_value_on(st); st->cr(); + st->print(BULLET"arrays: "); ik->array_klasses()->print_value_on(st); st->cr(); + st->print(BULLET"methods: "); ik->methods()->print_value_on(st); st->cr(); if (Verbose) { objArrayOop methods = ik->methods(); for(int i = 0; i < methods->length(); i++) { tty->print("%d : ", i); methods->obj_at(i)->print_value(); tty->cr(); } } - st->print(" - method ordering: "); ik->method_ordering()->print_value_on(st); st->cr(); - st->print(" - local interfaces: "); ik->local_interfaces()->print_value_on(st); st->cr(); - st->print(" - trans. interfaces: "); ik->transitive_interfaces()->print_value_on(st); st->cr(); - st->print(" - constants: "); ik->constants()->print_value_on(st); st->cr(); - st->print(" - class loader: "); ik->class_loader()->print_value_on(st); st->cr(); - st->print(" - protection domain: "); ik->protection_domain()->print_value_on(st); st->cr(); - st->print(" - host class: "); ik->host_klass()->print_value_on(st); st->cr(); - st->print(" - signers: "); ik->signers()->print_value_on(st); st->cr(); + st->print(BULLET"method ordering: "); ik->method_ordering()->print_value_on(st); st->cr(); + st->print(BULLET"local interfaces: "); ik->local_interfaces()->print_value_on(st); st->cr(); + st->print(BULLET"trans. interfaces: "); ik->transitive_interfaces()->print_value_on(st); st->cr(); + st->print(BULLET"constants: "); ik->constants()->print_value_on(st); st->cr(); + st->print(BULLET"class loader: "); ik->class_loader()->print_value_on(st); st->cr(); + st->print(BULLET"protection domain: "); ik->protection_domain()->print_value_on(st); st->cr(); + st->print(BULLET"host class: "); ik->host_klass()->print_value_on(st); st->cr(); + st->print(BULLET"signers: "); ik->signers()->print_value_on(st); st->cr(); if (ik->source_file_name() != NULL) { - st->print(" - source file: "); + st->print(BULLET"source file: "); ik->source_file_name()->print_value_on(st); st->cr(); } if (ik->source_debug_extension() != NULL) { - st->print(" - source debug extension: "); + st->print(BULLET"source debug extension: "); ik->source_debug_extension()->print_value_on(st); st->cr(); } - st->print_cr(" - previous version: "); { ResourceMark rm; // PreviousVersionInfo objects returned via PreviousVersionWalker @@ -564,38 +565,43 @@ // GrowableArray _after_ the PreviousVersionWalker destructor // has destroyed the handles. { + bool have_pv = false; PreviousVersionWalker pvw(ik); for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); pv_info != NULL; pv_info = pvw.next_previous_version()) { + if (!have_pv) + st->print(BULLET"previous version: "); + have_pv = true; pv_info->prev_constant_pool_handle()()->print_value_on(st); } - st->cr(); + if (have_pv) st->cr(); } // pvw is cleaned up } // rm is cleaned up if (ik->generic_signature() != NULL) { - st->print(" - generic signature: "); + st->print(BULLET"generic signature: "); ik->generic_signature()->print_value_on(st); + st->cr(); } - st->print(" - inner classes: "); ik->inner_classes()->print_value_on(st); st->cr(); - st->print(" - java mirror: "); ik->java_mirror()->print_value_on(st); st->cr(); - st->print(" - vtable length %d (start addr: " INTPTR_FORMAT ")", ik->vtable_length(), ik->start_of_vtable()); st->cr(); - st->print(" - itable length %d (start addr: " INTPTR_FORMAT ")", ik->itable_length(), ik->start_of_itable()); st->cr(); - st->print_cr(" - static fields:"); + st->print(BULLET"inner classes: "); ik->inner_classes()->print_value_on(st); st->cr(); + st->print(BULLET"java mirror: "); ik->java_mirror()->print_value_on(st); st->cr(); + st->print(BULLET"vtable length %d (start addr: " INTPTR_FORMAT ")", ik->vtable_length(), ik->start_of_vtable()); st->cr(); + st->print(BULLET"itable length %d (start addr: " INTPTR_FORMAT ")", ik->itable_length(), ik->start_of_itable()); st->cr(); + st->print_cr(BULLET"---- static fields (%d words):", ik->static_field_size()); FieldPrinter print_static_field(st); ik->do_local_static_fields(&print_static_field); - st->print_cr(" - non-static fields:"); - FieldPrinter print_nonstatic_field(st, obj); + st->print_cr(BULLET"---- non-static fields (%d words):", ik->nonstatic_field_size()); + FieldPrinter print_nonstatic_field(st); ik->do_nonstatic_fields(&print_nonstatic_field); - st->print(" - static oop maps: "); + st->print(BULLET"static oop maps: "); if (ik->static_oop_field_size() > 0) { int first_offset = ik->offset_of_static_fields(); st->print("%d-%d", first_offset, first_offset + ik->static_oop_field_size() - 1); } st->cr(); - st->print(" - non-static oop maps: "); + st->print(BULLET"non-static oop maps: "); OopMapBlock* map = ik->start_of_nonstatic_oop_maps(); OopMapBlock* end_map = map + ik->nonstatic_oop_map_size(); while (map < end_map) { diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/oops/klassVtable.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,9 +45,10 @@ klassOop super, objArrayOop methods, AccessFlags class_flags, - oop classloader, - symbolOop classname, - objArrayOop local_interfaces + Handle classloader, + symbolHandle classname, + objArrayOop local_interfaces, + TRAPS ) { No_Safepoint_Verifier nsv; @@ -64,9 +65,9 @@ int len = methods->length(); for (int i = 0; i < len; i++) { assert(methods->obj_at(i)->is_method(), "must be a methodOop"); - methodOop m = methodOop(methods->obj_at(i)); + methodHandle mh(THREAD, methodOop(methods->obj_at(i))); - if (needs_new_vtable_entry(m, super, classloader, classname, class_flags)) { + if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, THREAD)) { vtable_length += vtableEntry::size(); // we need a new entry } } @@ -117,6 +118,7 @@ superVtable->copy_vtable_to(table()); #ifndef PRODUCT if (PrintVtables && Verbose) { + ResourceMark rm; tty->print_cr("copy vtable from %s to %s size %d", sk->internal_name(), klass()->internal_name(), _length); } #endif @@ -159,13 +161,13 @@ int len = methods()->length(); int initialized = super_vtable_len; - // update_super_vtable can stop for gc - ensure using handles + // update_inherited_vtable can stop for gc - ensure using handles for (int i = 0; i < len; i++) { HandleMark hm(THREAD); assert(methods()->obj_at(i)->is_method(), "must be a methodOop"); methodHandle mh(THREAD, (methodOop)methods()->obj_at(i)); - bool needs_new_entry = update_super_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK); + bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK); if (needs_new_entry) { put_method_at(mh(), initialized); @@ -177,7 +179,7 @@ // add miranda methods; it will also update the value of initialized fill_in_mirandas(initialized); - // In class hierachieswhere the accesibility is not increasing (i.e., going from private -> + // In class hierarchies where the accessibility is not increasing (i.e., going from private -> // package_private -> publicprotected), the vtable might actually be smaller than our initial // calculation. assert(initialized <= _length, "vtable initialization failed"); @@ -188,26 +190,49 @@ } } -// Interates through the vtables to find the broadest access level. This -// will always be monotomic for valid Java programs - but not neccesarily -// for incompatible class files. -klassVtable::AccessType klassVtable::vtable_accessibility_at(int i) { - // This vtable is not implementing the specific method - if (i >= length()) return acc_private; +// Called for cases where a method does not override its superclass' vtable entry +// For bytecodes not produced by javac together it is possible that a method does not override +// the superclass's method, but might indirectly override a super-super class's vtable entry +// If none found, return a null superk, else return the superk of the method this does override +instanceKlass* klassVtable::find_transitive_override(instanceKlass* initialsuper, methodHandle target_method, + int vtable_index, Handle target_loader, symbolHandle target_classname, Thread * THREAD) { + instanceKlass* superk = initialsuper; + while (superk != NULL && superk->super() != NULL) { + instanceKlass* supersuperklass = instanceKlass::cast(superk->super()); + klassVtable* ssVtable = supersuperklass->vtable(); + if (vtable_index < ssVtable->length()) { + methodOop super_method = ssVtable->method_at(vtable_index); +#ifndef PRODUCT + symbolHandle name(THREAD,target_method()->name()); + symbolHandle signature(THREAD,target_method()->signature()); + assert(super_method->name() == name() && super_method->signature() == signature(), "vtable entry name/sig mismatch"); +#endif + if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) { +#ifndef PRODUCT + if (PrintVtables && Verbose) { + ResourceMark rm(THREAD); + tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ", + supersuperklass->internal_name(), + _klass->internal_name(), (target_method() != NULL) ? + target_method()->name()->as_C_string() : "", vtable_index); + super_method->access_flags().print_on(tty); + tty->print("overriders flags: "); + target_method->access_flags().print_on(tty); + tty->cr(); + } +#endif /*PRODUCT*/ + break; // return found superk + } + } else { + // super class has no vtable entry here, stop transitive search + superk = (instanceKlass*)NULL; + break; + } + // if no override found yet, continue to search up + superk = instanceKlass::cast(superk->super()); + } - // Compute AccessType for current method. public or protected we are done. - methodOop m = method_at(i); - if (m->is_protected() || m->is_public()) return acc_publicprotected; - - AccessType acc = m->is_package_private() ? acc_package_private : acc_private; - - // Compute AccessType for method in super classes - klassOop super = klass()->super(); - AccessType super_acc = (super != NULL) ? instanceKlass::cast(klass()->super())->vtable()->vtable_accessibility_at(i) - : acc_private; - - // Merge - return (AccessType)MAX2((int)acc, (int)super_acc); + return superk; } @@ -215,7 +240,8 @@ // OR return true if a new vtable entry is required // Only called for instanceKlass's, i.e. not for arrays // If that changed, could not use _klass as handle for klass -bool klassVtable::update_super_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS) { +bool klassVtable::update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, + bool checkconstraints, TRAPS) { ResourceMark rm; bool allocate_new = true; assert(klass->oop_is_instance(), "must be instanceKlass"); @@ -242,58 +268,35 @@ } // private methods always have a new entry in the vtable + // specification interpretation since classic has + // private methods not overriding if (target_method()->is_private()) { return allocate_new; } // search through the vtable and update overridden entries // Since check_signature_loaders acquires SystemDictionary_lock - // which can block for gc, once we are in this loop, use handles, not - // unhandled oops unless they are reinitialized for each loop - // handles for name, signature, klass, target_method - // not for match_method, holder + // which can block for gc, once we are in this loop, use handles + // For classfiles built with >= jdk7, we now look for transitive overrides symbolHandle name(THREAD,target_method()->name()); symbolHandle signature(THREAD,target_method()->signature()); + Handle target_loader(THREAD, _klass->class_loader()); + symbolHandle target_classname(THREAD, _klass->name()); for(int i = 0; i < super_vtable_len; i++) { - methodOop match_method = method_at(i); + methodOop super_method = method_at(i); // Check if method name matches - if (match_method->name() == name() && match_method->signature() == signature()) { - - instanceKlass* holder = (THREAD, instanceKlass::cast(match_method->method_holder())); - - // Check if the match_method is accessable from current class - - bool same_package_init = false; - bool same_package_flag = false; - bool simple_match = match_method->is_public() || match_method->is_protected(); - if (!simple_match) { - same_package_init = true; - same_package_flag = holder->is_same_class_package(_klass->class_loader(), _klass->name()); + if (super_method->name() == name() && super_method->signature() == signature()) { - simple_match = match_method->is_package_private() && same_package_flag; - } - // match_method is the superclass' method. Note we can't override - // and shouldn't access superclass' ACC_PRIVATE methods - // (although they have been copied into our vtable) - // A simple form of this statement is: - // if ( (match_method->is_public() || match_method->is_protected()) || - // (match_method->is_package_private() && holder->is_same_class_package(klass->class_loader(), klass->name()))) { - // - // The complexity is introduced it avoid recomputing 'is_same_class_package' which is expensive. - if (simple_match) { - // Check if target_method and match_method has same level of accessibility. The accesibility of the - // match method is the "most-general" visibility of all entries at it's particular vtable index for - // all superclasses. This check must be done before we override the current entry in the vtable. - AccessType at = vtable_accessibility_at(i); - bool same_access = false; + // get super_klass for method_holder for the found method + instanceKlass* super_klass = instanceKlass::cast(super_method->method_holder()); - if ( (at == acc_publicprotected && (target_method()->is_public() || target_method()->is_protected()) - || (at == acc_package_private && (target_method()->is_package_private() && - (( same_package_init && same_package_flag) || - (!same_package_init && holder->is_same_class_package(_klass->class_loader(), _klass->name()))))))) { - same_access = true; - } + if ((super_klass->is_override(super_method, target_loader, target_classname, THREAD)) || + ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION) + && ((super_klass = find_transitive_override(super_klass, target_method, i, target_loader, + target_classname, THREAD)) != (instanceKlass*)NULL))) { + // overriding, so no new entry + allocate_new = false; if (checkconstraints) { // Override vtable entry if passes loader constraint check @@ -302,15 +305,12 @@ // have already made any needed loader constraints. // Since loader constraints are transitive, it is enough // to link to the first super, and we get all the others. - symbolHandle signature(THREAD, target_method()->signature()); - Handle this_loader(THREAD, _klass->class_loader()); - instanceKlassHandle super_klass(THREAD, _klass->super()); Handle super_loader(THREAD, super_klass->class_loader()); - if (this_loader() != super_loader()) { + if (target_loader() != super_loader()) { ResourceMark rm(THREAD); char* failed_type_name = - SystemDictionary::check_signature_loaders(signature, this_loader, + SystemDictionary::check_signature_loaders(signature, target_loader, super_loader, true, CHECK_(false)); if (failed_type_name != NULL) { @@ -320,7 +320,7 @@ "(instance of %s), have different Class objects for the type " "%s used in the signature"; char* sig = target_method()->name_and_sig_as_C_string(); - const char* loader1 = SystemDictionary::loader_name(this_loader()); + const char* loader1 = SystemDictionary::loader_name(target_loader()); char* current = _klass->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(super_loader()); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + @@ -331,59 +331,46 @@ THROW_MSG_(vmSymbols::java_lang_LinkageError(), buf, false); } } - } - put_method_at(target_method(), i); - + } - if (same_access) { - // target and match has same accessiblity - share entry - allocate_new = false; - target_method()->set_vtable_index(i); + put_method_at(target_method(), i); + target_method()->set_vtable_index(i); #ifndef PRODUCT - if (PrintVtables && Verbose) { - AccessType targetacc; - if (target_method()->is_protected() || - target_method()->is_public()) { - targetacc = acc_publicprotected; - } else { - targetacc = target_method()->is_package_private() ? acc_package_private : acc_private; - } - tty->print_cr("overriding with %s::%s index %d, original flags: %x overriders flags: %x", - _klass->internal_name(), (target_method() != NULL) ? - target_method()->name()->as_C_string() : "", i, - at, targetacc); - } + if (PrintVtables && Verbose) { + tty->print("overriding with %s::%s index %d, original flags: ", + _klass->internal_name(), (target_method() != NULL) ? + target_method()->name()->as_C_string() : "", i); + super_method->access_flags().print_on(tty); + tty->print("overriders flags: "); + target_method->access_flags().print_on(tty); + tty->cr(); + } #endif /*PRODUCT*/ - } else { + } else { + // allocate_new = true; default. We might override one entry, + // but not override another. Once we override one, not need new #ifndef PRODUCT - if (PrintVtables && Verbose) { - AccessType targetacc; - if (target_method()->is_protected() || - target_method()->is_public()) { - targetacc = acc_publicprotected; - } else { - targetacc = target_method()->is_package_private() ? acc_package_private : acc_private; - } - tty->print_cr("override %s %s::%s at index %d, original flags: %x overriders flags: %x", - allocate_new ? "+ new" : "only", - _klass->internal_name(), (target_method() != NULL) ? - target_method()->name()->as_C_string() : "", i, - at, targetacc); - } + if (PrintVtables && Verbose) { + tty->print("NOT overriding with %s::%s index %d, original flags: ", + _klass->internal_name(), (target_method() != NULL) ? + target_method()->name()->as_C_string() : "", i); + super_method->access_flags().print_on(tty); + tty->print("overriders flags: "); + target_method->access_flags().print_on(tty); + tty->cr(); + } #endif /*PRODUCT*/ - } } } } return allocate_new; } - - void klassVtable::put_method_at(methodOop m, int index) { assert(m->is_oop_or_null(), "Not an oop or null"); #ifndef PRODUCT if (PrintVtables && Verbose) { + ResourceMark rm; tty->print_cr("adding %s::%s at index %d", _klass->internal_name(), (m != NULL) ? m->name()->as_C_string() : "", index); } @@ -397,19 +384,23 @@ // by "classloader" and "classname". // NOTE: The logic used here is very similar to the one used for computing // the vtables indices for a method. We cannot directly use that function because, -// when the Universe is boostrapping, a super's vtable might not be initialized. -bool klassVtable::needs_new_vtable_entry(methodOop target_method, +// we allocate the instanceKlass at load time, and that requires that the +// superclass has been loaded. +// However, the vtable entries are filled in at link time, and therefore +// the superclass' vtable may not yet have been filled in. +bool klassVtable::needs_new_vtable_entry(methodHandle target_method, klassOop super, - oop classloader, - symbolOop classname, - AccessFlags class_flags) { - if ((class_flags.is_final() || target_method->is_final()) || + Handle classloader, + symbolHandle classname, + AccessFlags class_flags, + TRAPS) { + if ((class_flags.is_final() || target_method()->is_final()) || // a final method never needs a new entry; final methods can be statically // resolved and they have to be present in the vtable only if they override // a super's method, in which case they re-use its entry - (target_method->is_static()) || + (target_method()->is_static()) || // static methods don't need to be in vtable - (target_method->name() == vmSymbols::object_initializer_name()) + (target_method()->name() == vmSymbols::object_initializer_name()) // is never called dynamically-bound ) { return false; @@ -421,55 +412,58 @@ } // private methods always have a new entry in the vtable - if (target_method->is_private()) { + // specification interpretation since classic has + // private methods not overriding + if (target_method()->is_private()) { return true; } // search through the super class hierarchy to see if we need // a new entry - symbolOop name = target_method->name(); - symbolOop signature = target_method->signature(); + ResourceMark rm; + symbolOop name = target_method()->name(); + symbolOop signature = target_method()->signature(); klassOop k = super; - methodOop match_method = NULL; + methodOop super_method = NULL; instanceKlass *holder = NULL; + methodOop recheck_method = NULL; while (k != NULL) { // lookup through the hierarchy for a method with matching name and sign. - match_method = instanceKlass::cast(k)->lookup_method(name, signature); - if (match_method == NULL) { + super_method = instanceKlass::cast(k)->lookup_method(name, signature); + if (super_method == NULL) { break; // we still have to search for a matching miranda method } // get the class holding the matching method - holder = instanceKlass::cast(match_method->method_holder()); - - if (!match_method->is_static()) { // we want only instance method matches - if ((target_method->is_public() || target_method->is_protected()) && - (match_method->is_public() || match_method->is_protected())) { - // target and match are public/protected; we do not need a new entry + // make sure you use that class for is_override + instanceKlass* superk = instanceKlass::cast(super_method->method_holder()); + // we want only instance method matches + // pretend private methods are not in the super vtable + // since we do override around them: e.g. a.m pub/b.m private/c.m pub, + // ignore private, c.m pub does override a.m pub + // For classes that were not javac'd together, we also do transitive overriding around + // methods that have less accessibility + if ((!super_method->is_static()) && + (!super_method->is_private())) { + if (superk->is_override(super_method, classloader, classname, THREAD)) { return false; - } - - if (target_method->is_package_private() && - match_method->is_package_private() && - holder->is_same_class_package(classloader, classname)) { - // target and match are P private; we do not need a new entry - return false; + // else keep looking for transitive overrides } } - k = holder->super(); // haven't found a match yet; continue to look + // Start with lookup result and continue to search up + k = superk->super(); // haven't found an override match yet; continue to look } // if the target method is public or protected it may have a matching // miranda method in the super, whose entry it should re-use. - if (target_method->is_public() || target_method->is_protected()) { - instanceKlass *sk = instanceKlass::cast(super); - if (sk->has_miranda_methods()) { - if (sk->lookup_method_in_all_interfaces(name, signature) != NULL) { - return false; // found a matching miranda; we do not need a new entry - } + // Actually, to handle cases that javac would not generate, we need + // this check for all access permissions. + instanceKlass *sk = instanceKlass::cast(super); + if (sk->has_miranda_methods()) { + if (sk->lookup_method_in_all_interfaces(name, signature) != NULL) { + return false; // found a matching miranda; we do not need a new entry } } - return true; // found no match; we need a new entry } @@ -884,7 +878,7 @@ _klass->name()->as_C_string()); - // Interate through all interfaces + // Iterate through all interfaces int i; for(i = 0; i < num_interfaces; i++) { itableOffsetEntry* ioe = offset_entry(i); @@ -1012,6 +1006,7 @@ new_method->name()->as_C_string(), new_method->signature()->as_C_string())); } + break; } ime++; } @@ -1153,6 +1148,27 @@ return index; } + +// inverse to compute_itable_index +methodOop klassItable::method_for_itable_index(klassOop intf, int itable_index) { + assert(instanceKlass::cast(intf)->is_interface(), "sanity check"); + objArrayOop methods = instanceKlass::cast(intf)->methods(); + + int index = itable_index; + // Adjust for , which is left out of table if first method + if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->name() == vmSymbols::class_initializer_name()) { + index++; + } + + if (itable_index < 0 || index >= methods->length()) + return NULL; // help caller defend against bad indexes + + methodOop m = (methodOop)methods->obj_at(index); + assert(compute_itable_index(m) == itable_index, "correct inverse"); + + return m; +} + void klassVtable::verify(outputStream* st, bool forced) { // make sure table is initialized if (!Universe::is_fully_initialized()) return; diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/oops/klassVtable.hpp --- a/src/share/vm/oops/klassVtable.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/oops/klassVtable.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,8 +70,9 @@ // conputes vtable length (in words) and the number of miranda methods static void compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods, klassOop super, objArrayOop methods, - AccessFlags class_flags, oop classloader, - symbolOop classname, objArrayOop local_interfaces); + AccessFlags class_flags, Handle classloader, + symbolHandle classname, objArrayOop local_interfaces, + TRAPS); // RedefineClasses() API support: // If any entry of this vtable points to any of old_methods, @@ -111,14 +112,16 @@ protected: friend class vtableEntry; private: + enum { VTABLE_TRANSITIVE_OVERRIDE_VERSION = 51 } ; void copy_vtable_to(vtableEntry* start); int initialize_from_super(KlassHandle super); int index_of(methodOop m, int len) const; // same as index_of, but search only up to len void put_method_at(methodOop m, int index); - static bool needs_new_vtable_entry(methodOop m, klassOop super, oop classloader, symbolOop classname, AccessFlags access_flags); - AccessType vtable_accessibility_at(int i); + static bool needs_new_vtable_entry(methodHandle m, klassOop super, Handle classloader, symbolHandle classname, AccessFlags access_flags, TRAPS); - bool update_super_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS); + bool update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS); + instanceKlass* find_transitive_override(instanceKlass* initialsuper, methodHandle target_method, int vtable_index, + Handle target_loader, symbolHandle target_classname, Thread* THREAD); // support for miranda methods bool is_miranda_entry_at(int i); @@ -298,6 +301,8 @@ // Resolving of method to index static int compute_itable_index(methodOop m); + // ...and back again: + static methodOop method_for_itable_index(klassOop klass, int itable_index); // Debugging/Statistics static void print_statistics() PRODUCT_RETURN; diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/oops/methodKlass.cpp --- a/src/share/vm/oops/methodKlass.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/oops/methodKlass.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -247,9 +247,14 @@ st->print_cr(" - size of params: %d", m->size_of_parameters()); st->print_cr(" - method size: %d", m->method_size()); st->print_cr(" - vtable index: %d", m->_vtable_index); + st->print_cr(" - i2i entry: " INTPTR_FORMAT, m->interpreter_entry()); + st->print_cr(" - adapter: " INTPTR_FORMAT, m->adapter()); + st->print_cr(" - compiled entry " INTPTR_FORMAT, m->from_compiled_entry()); st->print_cr(" - code size: %d", m->code_size()); - st->print_cr(" - code start: " INTPTR_FORMAT, m->code_base()); - st->print_cr(" - code end (excl): " INTPTR_FORMAT, m->code_base() + m->code_size()); + if (m->code_size() != 0) { + st->print_cr(" - code start: " INTPTR_FORMAT, m->code_base()); + st->print_cr(" - code end (excl): " INTPTR_FORMAT, m->code_base() + m->code_size()); + } if (m->method_data() != NULL) { st->print_cr(" - method data: " INTPTR_FORMAT, (address)m->method_data()); } @@ -293,6 +298,10 @@ m->code()->print_value_on(st); st->cr(); } + if (m->is_native()) { + st->print_cr(" - native function: " INTPTR_FORMAT, m->native_function()); + st->print_cr(" - signature handler: " INTPTR_FORMAT, m->signature_handler()); + } } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/oops/objArrayKlass.cpp --- a/src/share/vm/oops/objArrayKlass.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/oops/objArrayKlass.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -502,12 +502,25 @@ } } +static int max_objArray_print_length = 4; void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) { assert(obj->is_objArray(), "must be objArray"); + st->print("a "); element_klass()->print_value_on(st); - st->print("a [%d] ", objArrayOop(obj)->length()); - as_klassOop()->klass()->print_value_on(st); + int len = objArrayOop(obj)->length(); + st->print("[%d] ", len); + obj->print_address_on(st); + if (PrintOopAddress || PrintMiscellaneous && (WizardMode || Verbose)) { + st->print("{"); + for (int i = 0; i < len; i++) { + if (i > max_objArray_print_length) { + st->print("..."); break; + } + st->print(" "INTPTR_FORMAT, (intptr_t)(void*)objArrayOop(obj)->obj_at(i)); + } + st->print(" }"); + } } #endif // PRODUCT diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/oops/oop.cpp --- a/src/share/vm/oops/oop.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/oops/oop.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,11 +65,7 @@ void oopDesc::print_address_on(outputStream* st) const { if (PrintOopAddress) { - st->print("{"); - if (PrintOopAddress) { - st->print(INTPTR_FORMAT, this); - } - st->print("}"); + st->print("{"INTPTR_FORMAT"}", this); } } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/block.hpp --- a/src/share/vm/opto/block.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/block.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -371,6 +371,7 @@ Block *_broot; // Basic block of root uint _rpo_ctr; CFGLoop* _root_loop; + float _outer_loop_freq; // Outmost loop frequency // Per node latency estimation, valid only during GCM GrowableArray _node_latency; @@ -537,6 +538,7 @@ void compute_loop_depth(int depth); void compute_freq(); // compute frequency with loop assuming head freq 1.0f void scale_freq(); // scale frequency by loop trip count (including outer loops) + float outer_loop_freq() const; // frequency of outer loop bool in_loop_nest(Block* b); float trip_count() const { return 1.0f / _exit_prob; } virtual bool is_loop() { return true; } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/bytecodeInfo.cpp --- a/src/share/vm/opto/bytecodeInfo.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/bytecodeInfo.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -232,6 +232,14 @@ return "disallowed by CompilerOracle"; } + if (UseStringCache) { + // Do not inline StringCache::profile() method used only at the beginning. + if (callee_method->name() == ciSymbol::profile_name() && + callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) { + return "profiling method"; + } + } + return NULL; } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/c2_globals.hpp --- a/src/share/vm/opto/c2_globals.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/c2_globals.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -391,7 +391,7 @@ product(intx, EliminateAllocationArraySizeLimit, 64, \ "Array size (number of elements) limit for scalar replacement") \ \ - product(bool, UseOptoBiasInlining, true, \ + product(bool, UseOptoBiasInlining, true, \ "Generate biased locking code in C2 ideal graph") \ \ product(intx, ValueSearchLimit, 1000, \ @@ -410,7 +410,7 @@ "Miniumum %% of a successor (predecessor) for which block layout "\ "a will allow a fork (join) in a single chain") \ \ - product(bool, BlockLayoutRotateLoops, false, \ + product(bool, BlockLayoutRotateLoops, true, \ "Allow back branches to be fall throughs in the block layour") \ C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG) diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/chaitin.cpp --- a/src/share/vm/opto/chaitin.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/chaitin.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -149,6 +149,9 @@ #endif { NOT_PRODUCT( Compile::TracePhase t3("ctorChaitin", &_t_ctorChaitin, TimeCompiler); ) + + _high_frequency_lrg = MIN2(float(OPTO_LRG_HIGH_FREQ), _cfg._outer_loop_freq); + uint i,j; // Build a list of basic blocks, sorted by frequency _blks = NEW_RESOURCE_ARRAY( Block *, _cfg._num_blocks ); diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/chaitin.hpp --- a/src/share/vm/opto/chaitin.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/chaitin.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -338,6 +338,8 @@ Block **_blks; // Array of blocks sorted by frequency for coalescing + float _high_frequency_lrg; // Frequency at which LRG will be spilled for debug info + #ifndef PRODUCT bool _trace_spilling; #endif @@ -360,6 +362,8 @@ uint n2lidx( const Node *n ) const { return _names[n->_idx]; } + float high_frequency_lrg() const { return _high_frequency_lrg; } + #ifndef PRODUCT bool trace_spilling() const { return _trace_spilling; } #endif diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/coalesce.cpp --- a/src/share/vm/opto/coalesce.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/coalesce.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -473,7 +473,7 @@ } // End of is two-adr // Insert a copy at a debug use for a lrg which has high frequency - if( (b->_freq < OPTO_DEBUG_SPLIT_FREQ) && n->is_MachSafePoint() ) { + if( b->_freq < OPTO_DEBUG_SPLIT_FREQ || b->is_uncommon(_phc._cfg._bbs) ) { // Walk the debug inputs to the node and check for lrg freq JVMState* jvms = n->jvms(); uint debug_start = jvms ? jvms->debug_start() : 999999; @@ -487,7 +487,7 @@ LRG &lrg = lrgs(nidx); // If this lrg has a high frequency use/def - if( lrg._maxfreq >= OPTO_LRG_HIGH_FREQ ) { + if( lrg._maxfreq >= _phc.high_frequency_lrg() ) { // If the live range is also live out of this block (like it // would be for a fast/slow idiom), the normal spill mechanism // does an excellent job. If it is not live out of this block diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/gcm.cpp --- a/src/share/vm/opto/gcm.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/gcm.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1374,6 +1374,9 @@ _root_loop->_freq = 1.0; _root_loop->scale_freq(); + // Save outmost loop frequency for LRG frequency threshold + _outer_loop_freq = _root_loop->outer_loop_freq(); + // force paths ending at uncommon traps to be infrequent if (!C->do_freq_based_layout()) { Block_List worklist; @@ -1898,6 +1901,7 @@ // Do a top down traversal of loop tree (visit outer loops first.) void CFGLoop::scale_freq() { float loop_freq = _freq * trip_count(); + _freq = loop_freq; for (int i = 0; i < _members.length(); i++) { CFGElement* s = _members.at(i); float block_freq = s->_freq * loop_freq; @@ -1912,6 +1916,14 @@ } } +// Frequency of outer loop +float CFGLoop::outer_loop_freq() const { + if (_child != NULL) { + return _child->_freq; + } + return _freq; +} + #ifndef PRODUCT //------------------------------dump_tree-------------------------------------- void CFGLoop::dump_tree() const { diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/machnode.cpp --- a/src/share/vm/opto/machnode.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/machnode.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -340,6 +340,10 @@ if (base == NodeSentinel) return TypePtr::BOTTOM; const Type* t = base->bottom_type(); + if (UseCompressedOops && Universe::narrow_oop_shift() == 0) { + // 32-bit unscaled narrow oop can be the base of any address expression + t = t->make_ptr(); + } if (t->isa_intptr_t() && offset != 0 && offset != Type::OffsetBot) { // We cannot assert that the offset does not look oop-ish here. // Depending on the heap layout the cardmark base could land @@ -353,6 +357,7 @@ // be conservative if we do not recognize the type if (tp == NULL) { + assert(false, "this path may produce not optimal code"); return TypePtr::BOTTOM; } assert(tp->base() != Type::AnyPtr, "not a bare pointer"); diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/subnode.cpp --- a/src/share/vm/opto/subnode.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/subnode.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -639,8 +639,8 @@ int kps = (p0->isa_klassptr()?1:0) + (p1->isa_klassptr()?1:0); if (klass0 && klass1 && kps != 1 && // both or neither are klass pointers - !klass0->is_interface() && // do not trust interfaces - !klass1->is_interface()) { + klass0->is_loaded() && !klass0->is_interface() && // do not trust interfaces + klass1->is_loaded() && !klass1->is_interface()) { bool unrelated_classes = false; // See if neither subclasses the other, or if the class on top // is precise. In either of these cases, the compare is known diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/superword.cpp --- a/src/share/vm/opto/superword.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/superword.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -454,9 +454,13 @@ // or need to run igvn.optimize() again before SLP } else if (out->is_Phi() && out->bottom_type() == Type::MEMORY && !in_bb(out)) { // Ditto. Not sure what else to check further. - } else if (out->Opcode() == Op_StoreCM && out->in(4) == n) { + } else if (out->Opcode() == Op_StoreCM && out->in(MemNode::OopStore) == n) { // StoreCM has an input edge used as a precedence edge. // Maybe an issue when oop stores are vectorized. + } else if( out->is_MergeMem() && prev && + prev->Opcode() == Op_StoreCM && out == prev->in(MemNode::OopStore)) { + // Oop store is a MergeMem! This should not happen. Temporarily remove the assertion + // for this case because it could not be superwordized anyway. } else { assert(out == prev || prev == NULL, "no branches off of store slice"); } @@ -912,54 +916,175 @@ } } -//------------------------------co_locate_pack--------------------------- -// Within a pack, move stores down to the last executed store, -// and move loads up to the first executed load. +//-------------------------------remove_and_insert------------------- +//remove "current" from its current position in the memory graph and insert +//it after the appropriate insertion point (lip or uip) +void SuperWord::remove_and_insert(MemNode *current, MemNode *prev, MemNode *lip, + Node *uip, Unique_Node_List &sched_before) { + Node* my_mem = current->in(MemNode::Memory); + _igvn.hash_delete(current); + _igvn.hash_delete(my_mem); + + //remove current_store from its current position in the memmory graph + for (DUIterator i = current->outs(); current->has_out(i); i++) { + Node* use = current->out(i); + if (use->is_Mem()) { + assert(use->in(MemNode::Memory) == current, "must be"); + _igvn.hash_delete(use); + if (use == prev) { // connect prev to my_mem + use->set_req(MemNode::Memory, my_mem); + } else if (sched_before.member(use)) { + _igvn.hash_delete(uip); + use->set_req(MemNode::Memory, uip); + } else { + _igvn.hash_delete(lip); + use->set_req(MemNode::Memory, lip); + } + _igvn._worklist.push(use); + --i; //deleted this edge; rescan position + } + } + + bool sched_up = sched_before.member(current); + Node *insert_pt = sched_up ? uip : lip; + _igvn.hash_delete(insert_pt); + + // all uses of insert_pt's memory state should use current's instead + for (DUIterator i = insert_pt->outs(); insert_pt->has_out(i); i++) { + Node* use = insert_pt->out(i); + if (use->is_Mem()) { + assert(use->in(MemNode::Memory) == insert_pt, "must be"); + _igvn.hash_delete(use); + use->set_req(MemNode::Memory, current); + _igvn._worklist.push(use); + --i; //deleted this edge; rescan position + } else if (!sched_up && use->is_Phi() && use->bottom_type() == Type::MEMORY) { + uint pos; //lip (lower insert point) must be the last one in the memory slice + _igvn.hash_delete(use); + for (pos=1; pos < use->req(); pos++) { + if (use->in(pos) == insert_pt) break; + } + use->set_req(pos, current); + _igvn._worklist.push(use); + --i; + } + } + + //connect current to insert_pt + current->set_req(MemNode::Memory, insert_pt); + _igvn._worklist.push(current); +} + +//------------------------------co_locate_pack---------------------------------- +// To schedule a store pack, we need to move any sandwiched memory ops either before +// or after the pack, based upon dependence information: +// (1) If any store in the pack depends on the sandwiched memory op, the +// sandwiched memory op must be scheduled BEFORE the pack; +// (2) If a sandwiched memory op depends on any store in the pack, the +// sandwiched memory op must be scheduled AFTER the pack; +// (3) If a sandwiched memory op (say, memA) depends on another sandwiched +// memory op (say memB), memB must be scheduled before memA. So, if memA is +// scheduled before the pack, memB must also be scheduled before the pack; +// (4) If there is no dependence restriction for a sandwiched memory op, we simply +// schedule this store AFTER the pack +// (5) We know there is no dependence cycle, so there in no other case; +// (6) Finally, all memory ops in another single pack should be moved in the same direction. +// +// To schedule a load pack: the memory edge of every loads in the pack must be +// the same as the memory edge of the last executed load in the pack void SuperWord::co_locate_pack(Node_List* pk) { if (pk->at(0)->is_Store()) { - // Push Stores down towards last executed pack member MemNode* first = executed_first(pk)->as_Mem(); MemNode* last = executed_last(pk)->as_Mem(); - MemNode* insert_pt = last; + Unique_Node_List schedule_before_pack; + Unique_Node_List memops; + MemNode* current = last->in(MemNode::Memory)->as_Mem(); + MemNode* previous = last; while (true) { assert(in_bb(current), "stay in block"); + memops.push(previous); + for (DUIterator i = current->outs(); current->has_out(i); i++) { + Node* use = current->out(i); + if (use->is_Mem() && use != previous) + memops.push(use); + } + if(current == first) break; + previous = current; + current = current->in(MemNode::Memory)->as_Mem(); + } + + // determine which memory operations should be scheduled before the pack + for (uint i = 1; i < memops.size(); i++) { + Node *s1 = memops.at(i); + if (!in_pack(s1, pk) && !schedule_before_pack.member(s1)) { + for (uint j = 0; j< i; j++) { + Node *s2 = memops.at(j); + if (!independent(s1, s2)) { + if (in_pack(s2, pk) || schedule_before_pack.member(s2)) { + schedule_before_pack.push(s1); //s1 must be scheduled before + Node_List* mem_pk = my_pack(s1); + if (mem_pk != NULL) { + for (uint ii = 0; ii < mem_pk->size(); ii++) { + Node* s = mem_pk->at(ii); // follow partner + if (memops.member(s) && !schedule_before_pack.member(s)) + schedule_before_pack.push(s); + } + } + } + } + } + } + } + + MemNode* lower_insert_pt = last; + Node* upper_insert_pt = first->in(MemNode::Memory); + previous = last; //previous store in pk + current = last->in(MemNode::Memory)->as_Mem(); + + //start scheduling from "last" to "first" + while (true) { + assert(in_bb(current), "stay in block"); + assert(in_pack(previous, pk), "previous stays in pack"); Node* my_mem = current->in(MemNode::Memory); + if (in_pack(current, pk)) { - // Forward users of my memory state to my input memory state + // Forward users of my memory state (except "previous) to my input memory state _igvn.hash_delete(current); - _igvn.hash_delete(my_mem); for (DUIterator i = current->outs(); current->has_out(i); i++) { Node* use = current->out(i); - if (use->is_Mem()) { + if (use->is_Mem() && use != previous) { assert(use->in(MemNode::Memory) == current, "must be"); _igvn.hash_delete(use); - use->set_req(MemNode::Memory, my_mem); + if (schedule_before_pack.member(use)) { + _igvn.hash_delete(upper_insert_pt); + use->set_req(MemNode::Memory, upper_insert_pt); + } else { + _igvn.hash_delete(lower_insert_pt); + use->set_req(MemNode::Memory, lower_insert_pt); + } _igvn._worklist.push(use); --i; // deleted this edge; rescan position } } - // put current immediately before insert_pt - current->set_req(MemNode::Memory, insert_pt->in(MemNode::Memory)); - _igvn.hash_delete(insert_pt); - insert_pt->set_req(MemNode::Memory, current); - _igvn._worklist.push(insert_pt); - _igvn._worklist.push(current); - insert_pt = current; + previous = current; + } else { // !in_pack(current, pk) ==> a sandwiched store + remove_and_insert(current, previous, lower_insert_pt, upper_insert_pt, schedule_before_pack); } + if (current == first) break; current = my_mem->as_Mem(); - } - } else if (pk->at(0)->is_Load()) { - // Pull Loads up towards first executed pack member - LoadNode* first = executed_first(pk)->as_Load(); - Node* first_mem = first->in(MemNode::Memory); - _igvn.hash_delete(first_mem); - // Give each load same memory state as first + } // end while + } else if (pk->at(0)->is_Load()) { //load + // all use the memory state that the last executed load uses + LoadNode* last_load = executed_last(pk)->as_Load(); + Node* last_mem = last_load->in(MemNode::Memory); + _igvn.hash_delete(last_mem); + // Give each load same memory state as last for (uint i = 0; i < pk->size(); i++) { LoadNode* ld = pk->at(i)->as_Load(); _igvn.hash_delete(ld); - ld->set_req(MemNode::Memory, first_mem); + ld->set_req(MemNode::Memory, last_mem); _igvn._worklist.push(ld); } } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/opto/superword.hpp --- a/src/share/vm/opto/superword.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/opto/superword.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -341,8 +341,11 @@ void filter_packs(); // Adjust the memory graph for the packed operations void schedule(); - // Within a pack, move stores down to the last executed store, - // and move loads up to the first executed load. + // Remove "current" from its current position in the memory graph and insert + // it after the appropriate insert points (lip or uip); + void remove_and_insert(MemNode *current, MemNode *prev, MemNode *lip, Node *uip, Unique_Node_List &schd_before); + // Within a store pack, schedule stores together by moving out the sandwiched memory ops according + // to dependence info; and within a load pack, move loads down to the last executed load. void co_locate_pack(Node_List* p); // Convert packs into vector node operations void output(); diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/prims/jni.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -301,6 +301,10 @@ klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader, Handle(), &st, CHECK_NULL); + if (TraceClassResolution && k != NULL) { + trace_class_resolution(k); + } + cls = (jclass)JNIHandles::make_local( env, Klass::cast(k)->java_mirror()); return cls; @@ -365,6 +369,10 @@ result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, thread); + if (TraceClassResolution && result != NULL) { + trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); + } + // If we were the first invocation of jni_FindClass, we enable compilation again // rather than just allowing invocation counter to overflow and decay. // Controlled by flag DelayCompilationDuringStartup. @@ -2646,7 +2654,12 @@ Handle protection_domain; // null protection domain symbolHandle sym = oopFactory::new_symbol_handle(name, CHECK_NULL); - return find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL); + jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL); + + if (TraceClassResolution && result != NULL) { + trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); + } + return result; } // These lookups are done with the NULL (bootstrap) ClassLoader to diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/prims/jvm.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -64,6 +64,7 @@ ResourceMark rm; int line_number = -1; const char * source_file = NULL; + const char * trace = "explicit"; klassOop caller = NULL; JavaThread* jthread = JavaThread::current(); if (jthread->has_last_Java_frame()) { @@ -107,12 +108,21 @@ (last_caller->name() == vmSymbols::loadClassInternal_name() || last_caller->name() == vmSymbols::loadClass_name())) { found_it = true; + } else if (!vfst.at_end()) { + if (vfst.method()->is_native()) { + // JNI call + found_it = true; + } } if (found_it && !vfst.at_end()) { // found the caller caller = vfst.method()->method_holder(); line_number = vfst.method()->line_number_from_bci(vfst.bci()); - symbolOop s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name(); + if (line_number == -1) { + // show method name if it's a native method + trace = vfst.method()->name_and_sig_as_C_string(); + } + symbolOop s = instanceKlass::cast(caller)->source_file_name(); if (s != NULL) { source_file = s->as_C_string(); } @@ -124,15 +134,15 @@ const char * to = Klass::cast(to_class)->external_name(); // print in a single call to reduce interleaving between threads if (source_file != NULL) { - tty->print("RESOLVE %s %s %s:%d (explicit)\n", from, to, source_file, line_number); + tty->print("RESOLVE %s %s %s:%d (%s)\n", from, to, source_file, line_number, trace); } else { - tty->print("RESOLVE %s %s (explicit)\n", from, to); + tty->print("RESOLVE %s %s (%s)\n", from, to, trace); } } } } -static void trace_class_resolution(klassOop to_class) { +void trace_class_resolution(klassOop to_class) { EXCEPTION_MARK; trace_class_resolution_impl(to_class, THREAD); if (HAS_PENDING_EXCEPTION) { @@ -1242,7 +1252,7 @@ // Throws an exception if outer klass has not declared k as // an inner klass - Reflection::check_for_inner_class(k, inner_klass, CHECK_NULL); + Reflection::check_for_inner_class(k, inner_klass, true, CHECK_NULL); result->obj_at_put(members, inner_klass->java_mirror()); members++; @@ -1265,16 +1275,29 @@ JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass)) - const int inner_class_info_index = 0; - const int outer_class_info_index = 1; - +{ // ofClass is a reference to a java_lang_Class object. if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) { return NULL; } - instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); + symbolOop simple_name = NULL; + klassOop outer_klass + = instanceKlass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)) + )->compute_enclosing_class(simple_name, CHECK_NULL); + if (outer_klass == NULL) return NULL; // already a top-level class + if (simple_name == NULL) return NULL; // an anonymous class (inside a method) + return (jclass) JNIHandles::make_local(env, Klass::cast(outer_klass)->java_mirror()); +} +JVM_END + +// should be in instanceKlass.cpp, but is here for historical reasons +klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle k, + symbolOop& simple_name_result, TRAPS) { + Thread* thread = THREAD; + const int inner_class_info_index = inner_class_inner_class_info_offset; + const int outer_class_info_index = inner_class_outer_class_info_offset; if (k->inner_classes()->length() == 0) { // No inner class info => no declaring class @@ -1288,35 +1311,51 @@ bool found = false; klassOop ok; instanceKlassHandle outer_klass; + bool inner_is_member = false; + int simple_name_index = 0; // Find inner_klass attribute - for(int i = 0; i < i_length && !found; i+= 4) { + for (int i = 0; i < i_length && !found; i += inner_class_next_offset) { int ioff = i_icls->ushort_at(i + inner_class_info_index); int ooff = i_icls->ushort_at(i + outer_class_info_index); - - if (ioff != 0 && ooff != 0) { + int noff = i_icls->ushort_at(i + inner_class_inner_name_offset); + if (ioff != 0) { // Check to see if the name matches the class we're looking for // before attempting to find the class. if (i_cp->klass_name_at_matches(k, ioff)) { klassOop inner_klass = i_cp->klass_at(ioff, CHECK_NULL); - if (k() == inner_klass) { - found = true; + found = (k() == inner_klass); + if (found && ooff != 0) { ok = i_cp->klass_at(ooff, CHECK_NULL); outer_klass = instanceKlassHandle(thread, ok); + simple_name_index = noff; + inner_is_member = true; } } } } + if (found && outer_klass.is_null()) { + // It may be anonymous; try for that. + int encl_method_class_idx = k->enclosing_method_class_index(); + if (encl_method_class_idx != 0) { + ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL); + outer_klass = instanceKlassHandle(thread, ok); + inner_is_member = false; + } + } + // If no inner class attribute found for this class. - if (!found) return NULL; + if (outer_klass.is_null()) return NULL; // Throws an exception if outer klass has not declared k as an inner klass - Reflection::check_for_inner_class(outer_klass, k, CHECK_NULL); - - return (jclass)JNIHandles::make_local(env, outer_klass->java_mirror()); -JVM_END - + // We need evidence that each klass knows about the other, or else + // the system could allow a spoof of an inner class to gain access rights. + Reflection::check_for_inner_class(outer_klass, k, inner_is_member, CHECK_NULL); + + simple_name_result = (inner_is_member ? i_cp->symbol_at(simple_name_index) : symbolOop(NULL)); + return outer_klass(); +} JVM_ENTRY(jstring, JVM_GetClassSignature(JNIEnv *env, jclass cls)) assert (cls != NULL, "illegal class"); @@ -3213,8 +3252,12 @@ } Handle h_loader(THREAD, loader); Handle h_prot (THREAD, protection_domain); - return find_class_from_class_loader(env, name, true, h_loader, h_prot, - false, thread); + jclass result = find_class_from_class_loader(env, name, true, h_loader, h_prot, + false, thread); + if (TraceClassResolution && result != NULL) { + trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); + } + return result; JVM_END diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/prims/jvm_misc.hpp --- a/src/share/vm/prims/jvm_misc.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/prims/jvm_misc.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -27,6 +27,7 @@ jclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS); +void trace_class_resolution(klassOop to_class); /* * Support for Serialization and RMI. Currently used by HotSpot only. diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/fieldDescriptor.cpp --- a/src/share/vm/runtime/fieldDescriptor.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/fieldDescriptor.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,13 +107,14 @@ void fieldDescriptor::print_on_for(outputStream* st, oop obj) { print_on(st); BasicType ft = field_type(); - jint as_int; + jint as_int = 0; switch (ft) { case T_BYTE: as_int = (jint)obj->byte_field(offset()); st->print(" %d", obj->byte_field(offset())); break; case T_CHAR: + as_int = (jint)obj->char_field(offset()); { jchar c = obj->char_field(offset()); as_int = c; @@ -128,6 +129,7 @@ st->print(" %f", obj->float_field(offset())); break; case T_INT: + as_int = obj->int_field(offset()); st->print(" %d", obj->int_field(offset())); break; case T_LONG: @@ -144,12 +146,12 @@ break; case T_ARRAY: st->print(" "); - as_int = obj->int_field(offset()); + NOT_LP64(as_int = obj->int_field(offset())); obj->obj_field(offset())->print_value_on(st); break; case T_OBJECT: st->print(" "); - as_int = obj->int_field(offset()); + NOT_LP64(as_int = obj->int_field(offset())); obj->obj_field(offset())->print_value_on(st); break; default: @@ -158,9 +160,9 @@ } // Print a hint as to the underlying integer representation. This can be wrong for // pointers on an LP64 machine - if (ft == T_LONG || ft == T_DOUBLE) { + if (ft == T_LONG || ft == T_DOUBLE LP64_ONLY(|| !is_java_primitive(ft)) ) { st->print(" (%x %x)", obj->int_field(offset()), obj->int_field(offset()+sizeof(jint))); - } else { + } else if (as_int < 0 || as_int > 9) { st->print(" (%x)", as_int); } } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/globals.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -47,6 +47,7 @@ define_pd_global(intx, OnStackReplacePercentage, 0); define_pd_global(bool, ResizeTLAB, false); define_pd_global(intx, FreqInlineSize, 0); +define_pd_global(intx, InlineSmallCode, 0); define_pd_global(intx, NewSizeThreadIncrease, 4*K); define_pd_global(intx, NewRatio, 4); define_pd_global(intx, InlineClassNatives, true); @@ -1315,10 +1316,10 @@ \ product(intx, ParGCArrayScanChunk, 50, \ "Scan a subset and push remainder, if array is bigger than this") \ - \ product(bool, ParGCTrimOverflow, true, \ "Eagerly trim the overflow lists (useful for UseCompressedOops") \ \ + \ notproduct(bool, ParGCWorkQueueOverflowALot, false, \ "Whether we should simulate work queue overflow in ParNew") \ \ @@ -2619,7 +2620,7 @@ develop(intx, MaxRecursiveInlineLevel, 1, \ "maximum number of nested recursive calls that are inlined") \ \ - product(intx, InlineSmallCode, 1000, \ + product_pd(intx, InlineSmallCode, \ "Only inline already compiled methods if their code size is " \ "less than this") \ \ diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/handles.hpp --- a/src/share/vm/runtime/handles.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/handles.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -137,6 +137,14 @@ assert(is_null() || obj()->is_klass(), "not a klassOop"); } + // Direct interface, use very sparingly. + // Used by SystemDictionaryHandles to create handles on existing WKKs. + // The obj of such a klass handle may be null, because the handle is formed + // during system bootstrapping. + KlassHandle(klassOop *handle, bool dummy) : Handle((oop*)handle, dummy) { + assert(SharedSkipVerify || is_null() || obj() == NULL || obj()->is_klass(), "not a klassOop"); + } + // General access klassOop operator () () const { return obj(); } Klass* operator -> () const { return as_klass(); } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/orderAccess.cpp --- a/src/share/vm/runtime/orderAccess.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/orderAccess.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -26,3 +26,15 @@ # include "incls/_orderAccess.cpp.incl" volatile intptr_t OrderAccess::dummy = 0; + +void OrderAccess::StubRoutines_fence() { + // Use a stub if it exists. It may not exist during bootstrap so do + // nothing in that case but assert if no fence code exists after threads have been created + void (*func)() = CAST_TO_FN_PTR(void (*)(), StubRoutines::fence_entry()); + + if (func != NULL) { + (*func)(); + return; + } + assert(Threads::number_of_threads() == 0, "for bootstrap only"); +} diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/orderAccess.hpp --- a/src/share/vm/runtime/orderAccess.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/orderAccess.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -300,4 +300,10 @@ // In order to force a memory access, implementations may // need a volatile externally visible dummy variable. static volatile intptr_t dummy; + + private: + // This is a helper that invokes the StubRoutines::fence_entry() + // routine if it exists, It should only be used by platforms that + // don't another way to do the inline eassembly. + static void StubRoutines_fence(); }; diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/os.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -202,8 +202,10 @@ static char* attempt_reserve_memory_at(size_t bytes, char* addr); static void split_reserved_memory(char *base, size_t size, size_t split, bool realloc); - static bool commit_memory(char* addr, size_t bytes); - static bool commit_memory(char* addr, size_t size, size_t alignment_hint); + static bool commit_memory(char* addr, size_t bytes, + bool executable = false); + static bool commit_memory(char* addr, size_t size, size_t alignment_hint, + bool executable = false); static bool uncommit_memory(char* addr, size_t bytes); static bool release_memory(char* addr, size_t bytes); @@ -243,7 +245,8 @@ static char* non_memory_address_word(); // reserve, commit and pin the entire memory region - static char* reserve_memory_special(size_t size, char* addr = NULL); + static char* reserve_memory_special(size_t size, char* addr = NULL, + bool executable = false); static bool release_memory_special(char* addr, size_t bytes); static bool large_page_init(); static size_t large_page_size(); diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/reflection.cpp --- a/src/share/vm/runtime/reflection.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/reflection.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -554,10 +554,18 @@ return instanceKlass::cast(class1)->is_same_class_package(class2); } +bool Reflection::is_same_package_member(klassOop class1, klassOop class2, TRAPS) { + return instanceKlass::cast(class1)->is_same_package_member(class2, THREAD); +} + // Checks that the 'outer' klass has declared 'inner' as being an inner klass. If not, // throw an incompatible class change exception -void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, TRAPS) { +// If inner_is_member, require the inner to be a member of the outer. +// If !inner_is_member, require the inner to be anonymous (a non-member). +// Caller is responsible for figuring out in advance which case must be true. +void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, + bool inner_is_member, TRAPS) { const int inner_class_info_index = 0; const int outer_class_info_index = 1; @@ -567,7 +575,7 @@ int ioff = icls->ushort_at(i + inner_class_info_index); int ooff = icls->ushort_at(i + outer_class_info_index); - if (ioff != 0 && ooff != 0) { + if (inner_is_member && ioff != 0 && ooff != 0) { klassOop o = cp->klass_at(ooff, CHECK); if (o == outer()) { klassOop i = cp->klass_at(ioff, CHECK); @@ -576,6 +584,13 @@ } } } + if (!inner_is_member && ioff != 0 && ooff == 0 && + cp->klass_name_at_matches(inner, ioff)) { + klassOop i = cp->klass_at(ioff, CHECK); + if (i == inner()) { + return; + } + } } // 'inner' not declared as an inner klass in outer diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/reflection.hpp --- a/src/share/vm/runtime/reflection.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/reflection.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * 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,12 +87,18 @@ bool classloader_only, bool protected_restriction = false); static bool is_same_class_package(klassOop class1, klassOop class2); + static bool is_same_package_member(klassOop class1, klassOop class2, TRAPS); static bool can_relax_access_check_for( klassOop accessor, klassOop accesee, bool classloader_only); // inner class reflection - static void check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, TRAPS); + // raise an ICCE unless the required relationship can be proven to hold + // If inner_is_member, require the inner to be a member of the outer. + // If !inner_is_member, require the inner to be anonymous (a non-member). + // Caller is responsible for figuring out in advance which case must be true. + static void check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, + bool inner_is_member, TRAPS); // // Support for reflection based on dynamic bytecode generation (JDK 1.4) diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/sharedRuntime.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -675,48 +675,6 @@ JRT_END -// --------------------------------------------------------------------------------------------------------- -// Non-product code -#ifndef PRODUCT - -void SharedRuntime::verify_caller_frame(frame caller_frame, methodHandle callee_method) { - ResourceMark rm; - assert (caller_frame.is_interpreted_frame(), "sanity check"); - assert (callee_method->has_compiled_code(), "callee must be compiled"); - methodHandle caller_method (Thread::current(), caller_frame.interpreter_frame_method()); - jint bci = caller_frame.interpreter_frame_bci(); - methodHandle method = find_callee_method_inside_interpreter(caller_frame, caller_method, bci); - assert (callee_method == method, "incorrect method"); -} - -methodHandle SharedRuntime::find_callee_method_inside_interpreter(frame caller_frame, methodHandle caller_method, int bci) { - EXCEPTION_MARK; - Bytecode_invoke* bytecode = Bytecode_invoke_at(caller_method, bci); - methodHandle staticCallee = bytecode->static_target(CATCH); // Non-product code - - bytecode = Bytecode_invoke_at(caller_method, bci); - int bytecode_index = bytecode->index(); - Bytecodes::Code bc = bytecode->adjusted_invoke_code(); - - Handle receiver; - if (bc == Bytecodes::_invokeinterface || - bc == Bytecodes::_invokevirtual || - bc == Bytecodes::_invokespecial) { - symbolHandle signature (THREAD, staticCallee->signature()); - receiver = Handle(THREAD, retrieve_receiver(signature, caller_frame)); - } else { - receiver = Handle(); - } - CallInfo result; - constantPoolHandle constants (THREAD, caller_method->constants()); - LinkResolver::resolve_invoke(result, receiver, constants, bytecode_index, bc, CATCH); // Non-product code - methodHandle calleeMethod = result.selected_method(); - return calleeMethod; -} - -#endif // PRODUCT - - JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj)) assert(obj->is_oop(), "must be a valid oop"); assert(obj->klass()->klass_part()->has_finalizer(), "shouldn't be here otherwise"); diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/sharedRuntime.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,9 +180,6 @@ static oop retrieve_receiver( symbolHandle sig, frame caller ); - static void verify_caller_frame(frame caller_frame, methodHandle callee_method) PRODUCT_RETURN; - static methodHandle find_callee_method_inside_interpreter(frame caller_frame, methodHandle caller_method, int bci) PRODUCT_RETURN_(return methodHandle();); - static void register_finalizer(JavaThread* thread, oopDesc* obj); // dtrace notifications diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/thread.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -3007,17 +3007,19 @@ } if (UseStringCache) { - // Forcibly initialize java/lang/String and mutate the private + // Forcibly initialize java/lang/StringValue and mutate the private // static final "stringCacheEnabled" field before we start creating instances - klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_String(), Handle(), Handle(), CHECK_0); - KlassHandle k = KlassHandle(THREAD, k_o); - guarantee(k.not_null(), "Must find java/lang/String"); - instanceKlassHandle ik = instanceKlassHandle(THREAD, k()); - ik->initialize(CHECK_0); - fieldDescriptor fd; - // Possible we might not find this field; if so, don't break - if (ik->find_local_field(vmSymbols::stringCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) { - k()->bool_field_put(fd.offset(), true); + klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_StringValue(), Handle(), Handle(), CHECK_0); + // Possible that StringValue isn't present: if so, silently don't break + if (k_o != NULL) { + KlassHandle k = KlassHandle(THREAD, k_o); + instanceKlassHandle ik = instanceKlassHandle(THREAD, k()); + ik->initialize(CHECK_0); + fieldDescriptor fd; + // Possible we might not find this field: if so, silently don't break + if (ik->find_local_field(vmSymbols::stringCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) { + k()->bool_field_put(fd.offset(), true); + } } } } diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/virtualspace.cpp --- a/src/share/vm/runtime/virtualspace.cpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/virtualspace.cpp Thu Apr 02 05:22:02 2009 -0700 @@ -28,7 +28,7 @@ // ReservedSpace ReservedSpace::ReservedSpace(size_t size) { - initialize(size, 0, false, NULL, 0); + initialize(size, 0, false, NULL, 0, false); } ReservedSpace::ReservedSpace(size_t size, size_t alignment, @@ -36,7 +36,13 @@ char* requested_address, const size_t noaccess_prefix) { initialize(size+noaccess_prefix, alignment, large, requested_address, - noaccess_prefix); + noaccess_prefix, false); +} + +ReservedSpace::ReservedSpace(size_t size, size_t alignment, + bool large, + bool executable) { + initialize(size, alignment, large, NULL, 0, executable); } char * @@ -132,7 +138,8 @@ const bool try_reserve_special = UseLargePages && prefix_align == os::large_page_size(); if (!os::can_commit_large_page_memory() && try_reserve_special) { - initialize(size, prefix_align, true, requested_address, noaccess_prefix); + initialize(size, prefix_align, true, requested_address, noaccess_prefix, + false); return; } @@ -141,6 +148,7 @@ _alignment = 0; _special = false; _noaccess_prefix = 0; + _executable = false; // Assert that if noaccess_prefix is used, it is the same as prefix_align. assert(noaccess_prefix == 0 || @@ -189,7 +197,8 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, char* requested_address, - const size_t noaccess_prefix) { + const size_t noaccess_prefix, + bool executable) { const size_t granularity = os::vm_allocation_granularity(); assert((size & granularity - 1) == 0, "size not aligned to os::vm_allocation_granularity()"); @@ -201,6 +210,7 @@ _base = NULL; _size = 0; _special = false; + _executable = executable; _alignment = 0; _noaccess_prefix = 0; if (size == 0) { @@ -214,7 +224,7 @@ if (special) { - base = os::reserve_memory_special(size, requested_address); + base = os::reserve_memory_special(size, requested_address, executable); if (base != NULL) { // Check alignment constraints @@ -284,7 +294,7 @@ ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment, - bool special) { + bool special, bool executable) { assert((size % os::vm_allocation_granularity()) == 0, "size not allocation aligned"); _base = base; @@ -292,6 +302,7 @@ _alignment = alignment; _noaccess_prefix = 0; _special = special; + _executable = executable; } @@ -299,9 +310,10 @@ bool split, bool realloc) { assert(partition_size <= size(), "partition failed"); if (split) { - os::split_reserved_memory(_base, _size, partition_size, realloc); + os::split_reserved_memory(base(), size(), partition_size, realloc); } - ReservedSpace result(base(), partition_size, alignment, special()); + ReservedSpace result(base(), partition_size, alignment, special(), + executable()); return result; } @@ -310,7 +322,7 @@ ReservedSpace::last_part(size_t partition_size, size_t alignment) { assert(partition_size <= size(), "partition failed"); ReservedSpace result(base() + partition_size, size() - partition_size, - alignment, special()); + alignment, special(), executable()); return result; } @@ -348,6 +360,7 @@ _size = 0; _noaccess_prefix = 0; _special = false; + _executable = false; } } @@ -396,6 +409,14 @@ protect_noaccess_prefix(prefix_size+suffix_size); } +// Reserve space for code segment. Same as Java heap only we mark this as +// executable. +ReservedCodeSpace::ReservedCodeSpace(size_t r_size, + size_t rs_align, + bool large) : + ReservedSpace(r_size, rs_align, large, /*executable*/ true) { +} + // VirtualSpace VirtualSpace::VirtualSpace() { @@ -413,6 +434,7 @@ _middle_alignment = 0; _upper_alignment = 0; _special = false; + _executable = false; } @@ -426,6 +448,7 @@ _high = low(); _special = rs.special(); + _executable = rs.executable(); // When a VirtualSpace begins life at a large size, make all future expansion // and shrinking occur aligned to a granularity of large pages. This avoids @@ -483,6 +506,7 @@ _middle_alignment = 0; _upper_alignment = 0; _special = false; + _executable = false; } @@ -592,7 +616,7 @@ assert(low_boundary() <= lower_high() && lower_high() + lower_needs <= lower_high_boundary(), "must not expand beyond region"); - if (!os::commit_memory(lower_high(), lower_needs)) { + if (!os::commit_memory(lower_high(), lower_needs, _executable)) { debug_only(warning("os::commit_memory failed")); return false; } else { @@ -603,7 +627,8 @@ assert(lower_high_boundary() <= middle_high() && middle_high() + middle_needs <= middle_high_boundary(), "must not expand beyond region"); - if (!os::commit_memory(middle_high(), middle_needs, middle_alignment())) { + if (!os::commit_memory(middle_high(), middle_needs, middle_alignment(), + _executable)) { debug_only(warning("os::commit_memory failed")); return false; } @@ -613,7 +638,7 @@ assert(middle_high_boundary() <= upper_high() && upper_high() + upper_needs <= upper_high_boundary(), "must not expand beyond region"); - if (!os::commit_memory(upper_high(), upper_needs)) { + if (!os::commit_memory(upper_high(), upper_needs, _executable)) { debug_only(warning("os::commit_memory failed")); return false; } else { diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/runtime/virtualspace.hpp --- a/src/share/vm/runtime/virtualspace.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/runtime/virtualspace.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -32,12 +32,15 @@ size_t _noaccess_prefix; size_t _alignment; bool _special; + bool _executable; // ReservedSpace - ReservedSpace(char* base, size_t size, size_t alignment, bool special); + ReservedSpace(char* base, size_t size, size_t alignment, bool special, + bool executable); void initialize(size_t size, size_t alignment, bool large, char* requested_address, - const size_t noaccess_prefix); + const size_t noaccess_prefix, + bool executable); // Release parts of an already-reserved memory region [addr, addr + len) to // get a new region that has "compound alignment." Return the start of the @@ -75,16 +78,16 @@ const size_t suffix_size, const size_t suffix_align, char* requested_address, const size_t noaccess_prefix = 0); + ReservedSpace(size_t size, size_t alignment, bool large, bool executable); // Accessors - char* base() const { return _base; } - size_t size() const { return _size; } - size_t alignment() const { return _alignment; } - bool special() const { return _special; } - - size_t noaccess_prefix() const { return _noaccess_prefix; } - - bool is_reserved() const { return _base != NULL; } + char* base() const { return _base; } + size_t size() const { return _size; } + size_t alignment() const { return _alignment; } + bool special() const { return _special; } + bool executable() const { return _executable; } + size_t noaccess_prefix() const { return _noaccess_prefix; } + bool is_reserved() const { return _base != NULL; } void release(); // Splitting @@ -126,6 +129,13 @@ char* requested_address); }; +// Class encapsulating behavior specific memory space for Code +class ReservedCodeSpace : public ReservedSpace { + public: + // Constructor + ReservedCodeSpace(size_t r_size, size_t rs_align, bool large); +}; + // VirtualSpace is data structure for committing a previously reserved address range in smaller chunks. class VirtualSpace VALUE_OBJ_CLASS_SPEC { @@ -143,6 +153,9 @@ // os::commit_memory() or os::uncommit_memory(). bool _special; + // Need to know if commit should be executable. + bool _executable; + // MPSS Support // Each virtualspace region has a lower, middle, and upper region. // Each region has an end boundary and a high pointer which is the diff -r cea947c8a988 -r a80d48f6fde1 src/share/vm/utilities/globalDefinitions_visCPP.hpp --- a/src/share/vm/utilities/globalDefinitions_visCPP.hpp Sat Mar 28 15:47:29 2009 -0700 +++ b/src/share/vm/utilities/globalDefinitions_visCPP.hpp Thu Apr 02 05:22:02 2009 -0700 @@ -153,14 +153,6 @@ //---------------------------------------------------------------------------------------------------- // Miscellaneous -inline int vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr) { - // If number of characters written == count, Windows doesn't write a - // terminating NULL, so we do it ourselves. - int ret = _vsnprintf(buf, count, fmt, argptr); - if (count > 0) buf[count-1] = '\0'; - return ret; -} - // Visual Studio 2005 deprecates POSIX names - use ISO C++ names instead #if _MSC_VER >= 1400 #define open _open @@ -180,6 +172,17 @@ #pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union (needed in windows.h) #pragma warning( disable : 4511 ) // copy constructor could not be generated #pragma warning( disable : 4291 ) // no matching operator delete found; memory will not be freed if initialization thows an exception +#if _MSC_VER >= 1400 +#pragma warning( disable : 4996 ) // unsafe string functions. Same as define _CRT_SECURE_NO_WARNINGS/_CRT_SECURE_NO_DEPRICATE +#endif + +inline int vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr) { + // If number of characters written == count, Windows doesn't write a + // terminating NULL, so we do it ourselves. + int ret = _vsnprintf(buf, count, fmt, argptr); + if (count > 0) buf[count-1] = '\0'; + return ret; +} // Portability macros #define PRAGMA_INTERFACE diff -r cea947c8a988 -r a80d48f6fde1 test/compiler/6636138/Test1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6636138/Test1.java Thu Apr 02 05:22:02 2009 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6636138 + * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation. + * + * @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init -XX:+UseSuperword Test1 + */ + +class Test1 { + + public static void init(int src[], int [] dst, int[] ref) { + // initialize the arrays + for (int i =0; i 0; i--){ + int tmp = src[i]; + src[i] = src[i-1]; + src[i-1] = tmp; + } + } + + public static void verify(int src[]) { + for (int i = 0; i < src.length; i++){ + int value = (i-1 + src.length)%src.length; // correct value after shifting + if (src[i] != value) { + System.out.println("Error: src["+i+"] should be "+ value + " instead of " + src[i]); + System.exit(-1); + } + } + } + + public static void test() { + int[] src = new int[10]; + init(src); + shift(src); + verify(src); + } + + public static void main(String[] args) { + for (int i=0; i< 2000; i++) + test(); + } +}