changeset 2653:e9db47a083cc

Merge
author kevinw
date Thu, 11 Aug 2011 14:58:29 +0100
parents 41e6ee74f879 7c2653aefc46
children 87e40b34bc2b
files
diffstat 30 files changed, 835 insertions(+), 387 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Aug 02 14:37:35 2011 +0100
+++ b/.hgtags	Thu Aug 11 14:58:29 2011 +0100
@@ -172,3 +172,5 @@
 3aea9e9feb073f5500e031be6186666bcae89aa2 hs21-b11
 9ad1548c6b63d596c411afc35147ffd5254426d9 jdk7-b142
 9ad1548c6b63d596c411afc35147ffd5254426d9 hs21-b12
+c149193c768b8b7233da4c3a3fdc0756b975848e hs21-b13
+c149193c768b8b7233da4c3a3fdc0756b975848e jdk7-b143
--- a/.jcheck/conf	Tue Aug 02 14:37:35 2011 +0100
+++ b/.jcheck/conf	Thu Aug 11 14:58:29 2011 +0100
@@ -1,1 +1,1 @@
-project=jdk7
+project=jdk8
--- a/make/hotspot_version	Tue Aug 02 14:37:35 2011 +0100
+++ b/make/hotspot_version	Thu Aug 11 14:58:29 2011 +0100
@@ -38,8 +38,8 @@
 HS_BUILD_NUMBER=01
 
 JDK_MAJOR_VER=1
-JDK_MINOR_VER=7
+JDK_MINOR_VER=8
 JDK_MICRO_VER=0
 
 # Previous (bootdir) JDK version
-JDK_PREVIOUS_VERSION=1.6.0
+JDK_PREVIOUS_VERSION=1.7.0
--- a/make/jprt.gmk	Tue Aug 02 14:37:35 2011 +0100
+++ b/make/jprt.gmk	Thu Aug 11 14:58:29 2011 +0100
@@ -34,13 +34,13 @@
 endif
 
 jprt_build_productEmb:
-	$(MAKE) JAVASE_EMBEDDED=true jprt_build_product
+	$(MAKE) JAVASE_EMBEDDED=true MINIMIZE_RAM_USAGE=true jprt_build_product
 
 jprt_build_debugEmb:
-	$(MAKE) JAVASE_EMBEDDED=true jprt_build_debug
+	$(MAKE) JAVASE_EMBEDDED=true MINIMIZE_RAM_USAGE=true jprt_build_debug
 
 jprt_build_fastdebugEmb:
-	$(MAKE) JAVASE_EMBEDDED=true jprt_build_fastdebug
+	$(MAKE) JAVASE_EMBEDDED=true MINIMIZE_RAM_USAGE=true jprt_build_fastdebug
 
 jprt_build_productOpen:
 	$(MAKE) OPENJDK=true jprt_build_product
--- a/make/jprt.properties	Tue Aug 02 14:37:35 2011 +0100
+++ b/make/jprt.properties	Thu Aug 11 14:58:29 2011 +0100
@@ -50,7 +50,7 @@
 #       sparc etc.
 
 # Define the Solaris platforms we want for the various releases
-
+jprt.my.solaris.sparc.jdk8=solaris_sparc_5.10
 jprt.my.solaris.sparc.jdk7=solaris_sparc_5.10
 jprt.my.solaris.sparc.jdk7b107=solaris_sparc_5.10
 jprt.my.solaris.sparc.jdk7temp=solaris_sparc_5.10
@@ -64,6 +64,7 @@
 jprt.my.solaris.sparc.ejdk6=${jprt.my.solaris.sparc.jdk6}
 jprt.my.solaris.sparc=${jprt.my.solaris.sparc.${jprt.tools.default.release}}
 
+jprt.my.solaris.sparcv9.jdk8=solaris_sparcv9_5.10
 jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10
 jprt.my.solaris.sparcv9.jdk7b107=solaris_sparcv9_5.10
 jprt.my.solaris.sparcv9.jdk7temp=solaris_sparcv9_5.10
@@ -77,6 +78,7 @@
 jprt.my.solaris.sparcv9.ejdk6=${jprt.my.solaris.sparcv9.jdk6}
 jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}}
 
+jprt.my.solaris.i586.jdk8=solaris_i586_5.10
 jprt.my.solaris.i586.jdk7=solaris_i586_5.10
 jprt.my.solaris.i586.jdk7b107=solaris_i586_5.10
 jprt.my.solaris.i586.jdk7temp=solaris_i586_5.10
@@ -90,6 +92,7 @@
 jprt.my.solaris.i586.ejdk6=${jprt.my.solaris.i586.jdk6}
 jprt.my.solaris.i586=${jprt.my.solaris.i586.${jprt.tools.default.release}}
 
+jprt.my.solaris.x64.jdk8=solaris_x64_5.10
 jprt.my.solaris.x64.jdk7=solaris_x64_5.10
 jprt.my.solaris.x64.jdk7b107=solaris_x64_5.10
 jprt.my.solaris.x64.jdk7temp=solaris_x64_5.10
@@ -103,6 +106,7 @@
 jprt.my.solaris.x64.ejdk6=${jprt.my.solaris.x64.jdk6}
 jprt.my.solaris.x64=${jprt.my.solaris.x64.${jprt.tools.default.release}}
 
+jprt.my.linux.i586.jdk8=linux_i586_2.6
 jprt.my.linux.i586.jdk7=linux_i586_2.6
 jprt.my.linux.i586.jdk7b107=linux_i586_2.6
 jprt.my.linux.i586.jdk7temp=linux_i586_2.6
@@ -116,6 +120,7 @@
 jprt.my.linux.i586.ejdk6=linux_i586_2.6
 jprt.my.linux.i586=${jprt.my.linux.i586.${jprt.tools.default.release}}
 
+jprt.my.linux.x64.jdk8=linux_x64_2.6
 jprt.my.linux.x64.jdk7=linux_x64_2.6
 jprt.my.linux.x64.jdk7b107=linux_x64_2.6
 jprt.my.linux.x64.jdk7temp=linux_x64_2.6
@@ -129,6 +134,7 @@
 jprt.my.linux.x64.ejdk6=${jprt.my.linux.x64.jdk6}
 jprt.my.linux.x64=${jprt.my.linux.x64.${jprt.tools.default.release}}
 
+jprt.my.linux.ppc.jdk8=linux_ppc_2.6
 jprt.my.linux.ppc.jdk7=linux_ppc_2.6
 jprt.my.linux.ppc.jdk7b107=linux_ppc_2.6
 jprt.my.linux.ppc.jdk7temp=linux_ppc_2.6
@@ -136,6 +142,7 @@
 jprt.my.linux.ppc.ejdk7=linux_ppc_2.6
 jprt.my.linux.ppc=${jprt.my.linux.ppc.${jprt.tools.default.release}}
 
+jprt.my.linux.ppcv2.jdk8=linux_ppcv2_2.6
 jprt.my.linux.ppcv2.jdk7=linux_ppcv2_2.6
 jprt.my.linux.ppcv2.jdk7b107=linux_ppcv2_2.6
 jprt.my.linux.ppcv2.jdk7temp=linux_ppcv2_2.6
@@ -143,6 +150,7 @@
 jprt.my.linux.ppcv2.ejdk7=linux_ppcv2_2.6
 jprt.my.linux.ppcv2=${jprt.my.linux.ppcv2.${jprt.tools.default.release}}
 
+jprt.my.linux.ppcsflt.jdk8=linux_ppcsflt_2.6
 jprt.my.linux.ppcsflt.jdk7=linux_ppcsflt_2.6
 jprt.my.linux.ppcsflt.jdk7b107=linux_ppcsflt_2.6
 jprt.my.linux.ppcsflt.jdk7temp=linux_ppcsflt_2.6
@@ -150,6 +158,7 @@
 jprt.my.linux.ppcsflt.ejdk7=linux_ppcsflt_2.6
 jprt.my.linux.ppcsflt=${jprt.my.linux.ppcsflt.${jprt.tools.default.release}}
 
+jprt.my.linux.armvfp.jdk8=linux_armvfp_2.6
 jprt.my.linux.armvfp.jdk7=linux_armvfp_2.6
 jprt.my.linux.armvfp.jdk7b107=linux_armvfp_2.6
 jprt.my.linux.armvfp.jdk7temp=linux_armvfp_2.6
@@ -157,6 +166,7 @@
 jprt.my.linux.armvfp.ejdk7=linux_armvfp_2.6
 jprt.my.linux.armvfp=${jprt.my.linux.armvfp.${jprt.tools.default.release}}
 
+jprt.my.linux.armsflt.jdk8=linux_armsflt_2.6
 jprt.my.linux.armsflt.jdk7=linux_armsflt_2.6
 jprt.my.linux.armsflt.jdk7b107=linux_armsflt_2.6
 jprt.my.linux.armsflt.jdk7temp=linux_armsflt_2.6
@@ -164,6 +174,7 @@
 jprt.my.linux.armsflt.ejdk7=linux_armsflt_2.6
 jprt.my.linux.armsflt=${jprt.my.linux.armsflt.${jprt.tools.default.release}}
 
+jprt.my.windows.i586.jdk8=windows_i586_5.1
 jprt.my.windows.i586.jdk7=windows_i586_5.1
 jprt.my.windows.i586.jdk7b107=windows_i586_5.0
 jprt.my.windows.i586.jdk7temp=windows_i586_5.0
@@ -177,6 +188,7 @@
 jprt.my.windows.i586.ejdk6=${jprt.my.windows.i586.jdk6}
 jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}}
 
+jprt.my.windows.x64.jdk8=windows_x64_5.2
 jprt.my.windows.x64.jdk7=windows_x64_5.2
 jprt.my.windows.x64.jdk7b107=windows_x64_5.2
 jprt.my.windows.x64.jdk7temp=windows_x64_5.2
@@ -218,6 +230,7 @@
 jprt.build.targets.all=${jprt.build.targets.standard}, \
     ${jprt.build.targets.embedded}, ${jprt.build.targets.open}
 
+jprt.build.targets.jdk8=${jprt.build.targets.all}
 jprt.build.targets.jdk7=${jprt.build.targets.all}
 jprt.build.targets.jdk7temp=${jprt.build.targets.all}
 jprt.build.targets.jdk7b107=${jprt.build.targets.all}
@@ -494,6 +507,7 @@
   ${jprt.my.windows.x64.test.targets}
 
 
+jprt.test.targets.jdk8=${jprt.test.targets.standard}
 jprt.test.targets.jdk7=${jprt.test.targets.standard}
 jprt.test.targets.jdk7temp=${jprt.test.targets.standard}
 jprt.test.targets.jdk7b105=${jprt.test.targets.standard}
@@ -534,6 +548,7 @@
 jprt.make.rule.test.targets.embedded = \
   ${jprt.make.rule.test.targets.standard.client}
 
+jprt.make.rule.test.targets.jdk8=${jprt.make.rule.test.targets.standard}
 jprt.make.rule.test.targets.jdk7=${jprt.make.rule.test.targets.standard}
 jprt.make.rule.test.targets.jdk7temp=${jprt.make.rule.test.targets.standard}
 jprt.make.rule.test.targets.jdk7b107=${jprt.make.rule.test.targets.standard}
--- a/src/cpu/sparc/vm/assembler_sparc.hpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp	Thu Aug 11 14:58:29 2011 +0100
@@ -716,6 +716,8 @@
     casa_op3     = 0x3c,
     casxa_op3    = 0x3e,
 
+    mftoi_op3    = 0x36,
+
     alt_bit_op3  = 0x10,
      cc_bit_op3  = 0x10
   };
@@ -750,7 +752,13 @@
     fitod_opf   = 0xc8,
     fstod_opf   = 0xc9,
     fstoi_opf   = 0xd1,
-    fdtoi_opf   = 0xd2
+    fdtoi_opf   = 0xd2,
+
+    mdtox_opf   = 0x110,
+    mstouw_opf  = 0x111,
+    mstosw_opf  = 0x113,
+    mxtod_opf   = 0x118,
+    mwtos_opf   = 0x119
   };
 
   enum RCondition {  rc_z = 1,  rc_lez = 2,  rc_lz = 3, rc_nz = 5, rc_gz = 6, rc_gez = 7  };
@@ -1061,6 +1069,9 @@
     return x & ((1 << 10) - 1);
   }
 
+  // instruction only in VIS3
+  static void vis3_only() { assert( VM_Version::has_vis3(), "This instruction only works on SPARC with VIS3"); }
+
   // instruction only in v9
   static void v9_only() { assert( VM_Version::v9_instructions_work(), "This instruction only works on SPARC V9"); }
 
@@ -1247,8 +1258,8 @@
 
   // pp 159
 
-  void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only();  emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); }
-  void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) {             emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); }
+  void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only();  emit_long( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); }
+  void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) {             emit_long( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); }
 
   // pp 160
 
@@ -1256,8 +1267,8 @@
 
   // pp 161
 
-  void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only();  emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, w)); }
-  void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) {             emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, w)); }
+  void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only();  emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, FloatRegisterImpl::D)); }
+  void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) {             emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, FloatRegisterImpl::S)); }
 
   // pp 162
 
@@ -1709,6 +1720,19 @@
   inline void wrasi(  Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); }
   inline void wrfprs( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); }
 
+
+  // VIS3 instructions
+
+  void movstosw( FloatRegister s, Register d ) { vis3_only();  emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); }
+  void movstouw( FloatRegister s, Register d ) { vis3_only();  emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstouw_opf) | fs2(s, FloatRegisterImpl::S)); }
+  void movdtox(  FloatRegister s, Register d ) { vis3_only();  emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mdtox_opf) | fs2(s, FloatRegisterImpl::D)); }
+
+  void movwtos( Register s, FloatRegister d ) { vis3_only();  emit_long( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); }
+  void movxtod( Register s, FloatRegister d ) { vis3_only();  emit_long( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); }
+
+
+
+
   // For a given register condition, return the appropriate condition code
   // Condition (the one you would use to get the same effect after "tst" on
   // the target register.)
--- a/src/cpu/sparc/vm/methodHandles_sparc.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -524,6 +524,30 @@
 }
 #endif // ASSERT
 
+
+void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp) {
+  assert(method == G5_method, "interpreter calling convention");
+  __ verify_oop(method);
+  __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_interpreted_offset()), target);
+  if (JvmtiExport::can_post_interpreter_events()) {
+    // JVMTI events, such as single-stepping, are implemented partly by avoiding running
+    // compiled code in threads for which the event is enabled.  Check here for
+    // interp_only_mode if these events CAN be enabled.
+    __ verify_thread();
+    Label skip_compiled_code;
+
+    const Address interp_only(G2_thread, JavaThread::interp_only_mode_offset());
+    __ ld(interp_only, temp);
+    __ tst(temp);
+    __ br(Assembler::notZero, true, Assembler::pn, skip_compiled_code);
+    __ delayed()->ld_ptr(G5_method, in_bytes(methodOopDesc::interpreter_entry_offset()), target);
+    __ bind(skip_compiled_code);
+  }
+  __ jmp(target, 0);
+  __ delayed()->nop();
+}
+
+
 // Code generation
 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
   // I5_savedSP/O5_savedSP: sender SP (must preserve)
@@ -1105,9 +1129,6 @@
   guarantee(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
 
   // Some handy addresses:
-  Address G5_method_fie(    G5_method,        in_bytes(methodOopDesc::from_interpreted_offset()));
-  Address G5_method_fce(    G5_method,        in_bytes(methodOopDesc::from_compiled_offset()));
-
   Address G3_mh_vmtarget(   G3_method_handle, java_lang_invoke_MethodHandle::vmtarget_offset_in_bytes());
 
   Address G3_dmh_vmindex(   G3_method_handle, java_lang_invoke_DirectMethodHandle::vmindex_offset_in_bytes());
@@ -1136,24 +1157,23 @@
   case _raise_exception:
     {
       // Not a real MH entry, but rather shared code for raising an
-      // exception.  Since we use the compiled entry, arguments are
-      // expected in compiler argument registers.
+      // exception.  For sharing purposes the arguments are passed into registers
+      // and then placed in the intepreter calling convention here.
       assert(raise_exception_method(), "must be set");
       assert(raise_exception_method()->from_compiled_entry(), "method must be linked");
 
-      __ mov(O5_savedSP, SP);  // Cut the stack back to where the caller started.
-
-      Label L_no_method;
-      // FIXME: fill in _raise_exception_method with a suitable java.lang.invoke method
       __ set(AddressLiteral((address) &_raise_exception_method), G5_method);
       __ ld_ptr(Address(G5_method, 0), G5_method);
 
       const int jobject_oop_offset = 0;
       __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method);
 
-      __ verify_oop(G5_method);
-      __ jump_indirect_to(G5_method_fce, O3_scratch);  // jump to compiled entry
-      __ delayed()->nop();
+      adjust_SP_and_Gargs_down_by_slots(_masm, 3, noreg, noreg);
+
+      __ st_ptr(O0_code,     __ argument_address(constant(2), noreg, 0));
+      __ st_ptr(O1_actual,   __ argument_address(constant(1), noreg, 0));
+      __ st_ptr(O2_required, __ argument_address(constant(0), noreg, 0));
+      jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
     }
     break;
 
@@ -1161,7 +1181,6 @@
   case _invokespecial_mh:
     {
       __ load_heap_oop(G3_mh_vmtarget, G5_method);  // target is a methodOop
-      __ verify_oop(G5_method);
       // Same as TemplateTable::invokestatic or invokespecial,
       // minus the CP setup and profiling:
       if (ek == _invokespecial_mh) {
@@ -1171,8 +1190,7 @@
         __ null_check(G3_method_handle);
         __ verify_oop(G3_method_handle);
       }
-      __ jump_indirect_to(G5_method_fie, O1_scratch);
-      __ delayed()->nop();
+      jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
     }
     break;
 
@@ -1204,9 +1222,7 @@
       Address vtable_entry_addr(O0_klass, base + vtableEntry::method_offset_in_bytes());
       __ ld_ptr(vtable_entry_addr, G5_method);
 
-      __ verify_oop(G5_method);
-      __ jump_indirect_to(G5_method_fie, O1_scratch);
-      __ delayed()->nop();
+      jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
     }
     break;
 
@@ -1237,9 +1253,7 @@
                                  O3_scratch,
                                  no_such_interface);
 
-      __ verify_oop(G5_method);
-      __ jump_indirect_to(G5_method_fie, O1_scratch);
-      __ delayed()->nop();
+      jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
 
       __ bind(no_such_interface);
       // Throw an exception.
@@ -1283,9 +1297,7 @@
 
       if (direct_to_method) {
         __ load_heap_oop(G3_mh_vmtarget, G5_method);  // target is a methodOop
-        __ verify_oop(G5_method);
-        __ jump_indirect_to(G5_method_fie, O1_scratch);
-        __ delayed()->nop();
+        jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
       } else {
         __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);  // target is a methodOop
         __ verify_oop(G3_method_handle);
--- a/src/cpu/sparc/vm/methodHandles_sparc.hpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/cpu/sparc/vm/methodHandles_sparc.hpp	Thu Aug 11 14:58:29 2011 +0100
@@ -221,4 +221,8 @@
                  "reference is a MH");
   }
 
+  // Similar to InterpreterMacroAssembler::jump_from_interpreted.
+  // Takes care of special dispatch from single stepping too.
+  static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, Register temp2);
+
   static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
--- a/src/cpu/sparc/vm/sparc.ad	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/cpu/sparc/vm/sparc.ad	Thu Aug 11 14:58:29 2011 +0100
@@ -425,7 +425,7 @@
 // but they are used with the "Op_RegD" type, and always occur in even/odd pairs.
 // This class is usable for mis-aligned loads as happen in I2C adapters.
 reg_class dflt_low_reg(R_F0, R_F1, R_F2, R_F3, R_F4, R_F5, R_F6, R_F7, R_F8, R_F9, R_F10,R_F11,R_F12,R_F13,R_F14,R_F15,
-                   R_F16,R_F17,R_F18,R_F19,R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29,R_F30,R_F31 );
+                   R_F16,R_F17,R_F18,R_F19,R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29);
 %}
 
 //----------DEFINITION BLOCK---------------------------------------------------
@@ -1326,17 +1326,17 @@
 
   // --------------------------------------
   // Check for float->int copy; requires a trip through memory
-  if( src_first_rc == rc_float && dst_first_rc == rc_int ) {
+  if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS < 3) {
     int offset = frame::register_save_words*wordSize;
-    if( cbuf ) {
+    if (cbuf) {
       emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16 );
       impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st);
       impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st);
       emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16 );
     }
 #ifndef PRODUCT
-    else if( !do_size ) {
-      if( size != 0 ) st->print("\n\t");
+    else if (!do_size) {
+      if (size != 0) st->print("\n\t");
       st->print(  "SUB    R_SP,16,R_SP\n");
       impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st);
       impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st);
@@ -1346,6 +1346,21 @@
     size += 16;
   }
 
+  // Check for float->int copy on T4
+  if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS >= 3) {
+    // Further check for aligned-adjacent pair, so we can use a double move
+    if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second)
+      return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mdtox_opf,"MOVDTOX",size, st);
+    size  =  impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mstouw_opf,"MOVSTOUW",size, st);
+  }
+  // Check for int->float copy on T4
+  if (src_first_rc == rc_int && dst_first_rc == rc_float && UseVIS >= 3) {
+    // Further check for aligned-adjacent pair, so we can use a double move
+    if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second)
+      return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mxtod_opf,"MOVXTOD",size, st);
+    size  =  impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mwtos_opf,"MOVWTOS",size, st);
+  }
+
   // --------------------------------------
   // In the 32-bit 1-reg-longs build ONLY, I see mis-aligned long destinations.
   // In such cases, I have to do the big-endian swap.  For aligned targets, the
@@ -8164,6 +8179,155 @@
   ins_pipe( cadd_cmpltmask );
 %}
 
+
+//-----------------------------------------------------------------
+// Direct raw moves between float and general registers using VIS3.
+
+//  ins_pipe(faddF_reg);
+instruct MoveF2I_reg_reg(iRegI dst, regF src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (MoveF2I src));
+
+  format %{ "MOVSTOUW $src,$dst\t! MoveF2I" %}
+  ins_encode %{
+    __ movstouw($src$$FloatRegister, $dst$$Register);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct MoveI2F_reg_reg(regF dst, iRegI src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (MoveI2F src));
+
+  format %{ "MOVWTOS $src,$dst\t! MoveI2F" %}
+  ins_encode %{
+    __ movwtos($src$$Register, $dst$$FloatRegister);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct MoveD2L_reg_reg(iRegL dst, regD src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (MoveD2L src));
+
+  format %{ "MOVDTOX $src,$dst\t! MoveD2L" %}
+  ins_encode %{
+    __ movdtox(as_DoubleFloatRegister($src$$reg), $dst$$Register);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct MoveL2D_reg_reg(regD dst, iRegL src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (MoveL2D src));
+
+  format %{ "MOVXTOD $src,$dst\t! MoveL2D" %}
+  ins_encode %{
+    __ movxtod($src$$Register, as_DoubleFloatRegister($dst$$reg));
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+
+// Raw moves between float and general registers using stack.
+
+instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{
+  match(Set dst (MoveF2I src));
+  effect(DEF dst, USE src);
+  ins_cost(MEMORY_REF_COST);
+
+  size(4);
+  format %{ "LDUW   $src,$dst\t! MoveF2I" %}
+  opcode(Assembler::lduw_op3);
+  ins_encode(simple_form3_mem_reg( src, dst ) );
+  ins_pipe(iload_mem);
+%}
+
+instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{
+  match(Set dst (MoveI2F src));
+  effect(DEF dst, USE src);
+  ins_cost(MEMORY_REF_COST);
+
+  size(4);
+  format %{ "LDF    $src,$dst\t! MoveI2F" %}
+  opcode(Assembler::ldf_op3);
+  ins_encode(simple_form3_mem_reg(src, dst));
+  ins_pipe(floadF_stk);
+%}
+
+instruct MoveD2L_stack_reg(iRegL dst, stackSlotD src) %{
+  match(Set dst (MoveD2L src));
+  effect(DEF dst, USE src);
+  ins_cost(MEMORY_REF_COST);
+
+  size(4);
+  format %{ "LDX    $src,$dst\t! MoveD2L" %}
+  opcode(Assembler::ldx_op3);
+  ins_encode(simple_form3_mem_reg( src, dst ) );
+  ins_pipe(iload_mem);
+%}
+
+instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{
+  match(Set dst (MoveL2D src));
+  effect(DEF dst, USE src);
+  ins_cost(MEMORY_REF_COST);
+
+  size(4);
+  format %{ "LDDF   $src,$dst\t! MoveL2D" %}
+  opcode(Assembler::lddf_op3);
+  ins_encode(simple_form3_mem_reg(src, dst));
+  ins_pipe(floadD_stk);
+%}
+
+instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{
+  match(Set dst (MoveF2I src));
+  effect(DEF dst, USE src);
+  ins_cost(MEMORY_REF_COST);
+
+  size(4);
+  format %{ "STF   $src,$dst\t! MoveF2I" %}
+  opcode(Assembler::stf_op3);
+  ins_encode(simple_form3_mem_reg(dst, src));
+  ins_pipe(fstoreF_stk_reg);
+%}
+
+instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{
+  match(Set dst (MoveI2F src));
+  effect(DEF dst, USE src);
+  ins_cost(MEMORY_REF_COST);
+
+  size(4);
+  format %{ "STW    $src,$dst\t! MoveI2F" %}
+  opcode(Assembler::stw_op3);
+  ins_encode(simple_form3_mem_reg( dst, src ) );
+  ins_pipe(istore_mem_reg);
+%}
+
+instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{
+  match(Set dst (MoveD2L src));
+  effect(DEF dst, USE src);
+  ins_cost(MEMORY_REF_COST);
+
+  size(4);
+  format %{ "STDF   $src,$dst\t! MoveD2L" %}
+  opcode(Assembler::stdf_op3);
+  ins_encode(simple_form3_mem_reg(dst, src));
+  ins_pipe(fstoreD_stk_reg);
+%}
+
+instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{
+  match(Set dst (MoveL2D src));
+  effect(DEF dst, USE src);
+  ins_cost(MEMORY_REF_COST);
+
+  size(4);
+  format %{ "STX    $src,$dst\t! MoveL2D" %}
+  opcode(Assembler::stx_op3);
+  ins_encode(simple_form3_mem_reg( dst, src ) );
+  ins_pipe(istore_mem_reg);
+%}
+
+
 //----------Arithmetic Conversion Instructions---------------------------------
 // The conversions operations are all Alpha sorted.  Please keep it that way!
 
@@ -8191,7 +8355,7 @@
   ins_pipe(fcvtD2I);
 %}
 
-instruct convD2I_reg(stackSlotI dst, regD src) %{
+instruct convD2I_stk(stackSlotI dst, regD src) %{
   match(Set dst (ConvD2I src));
   ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST);
   expand %{
@@ -8201,6 +8365,18 @@
   %}
 %}
 
+instruct convD2I_reg(iRegI dst, regD src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (ConvD2I src));
+  ins_cost(DEFAULT_COST*2 + BRANCH_COST);
+  expand %{
+    regF tmp;
+    convD2I_helper(tmp, src);
+    MoveF2I_reg_reg(dst, tmp);
+  %}
+%}
+
+
 // Convert a double to a long in a double register.
 // If the double is a NAN, stuff a zero in instead.
 instruct convD2L_helper(regD dst, regD src, flagsRegF0 fcc0) %{
@@ -8215,9 +8391,7 @@
   ins_pipe(fcvtD2L);
 %}
 
-
-// Double to Long conversion
-instruct convD2L_reg(stackSlotL dst, regD src) %{
+instruct convD2L_stk(stackSlotL dst, regD src) %{
   match(Set dst (ConvD2L src));
   ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST);
   expand %{
@@ -8227,6 +8401,17 @@
   %}
 %}
 
+instruct convD2L_reg(iRegL dst, regD src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (ConvD2L src));
+  ins_cost(DEFAULT_COST*2 + BRANCH_COST);
+  expand %{
+    regD tmp;
+    convD2L_helper(tmp, src);
+    MoveD2L_reg_reg(dst, tmp);
+  %}
+%}
+
 
 instruct convF2D_reg(regD dst, regF src) %{
   match(Set dst (ConvF2D src));
@@ -8237,6 +8422,8 @@
 %}
 
 
+// Convert a float to an int in a float register.
+// If the float is a NAN, stuff a zero in instead.
 instruct convF2I_helper(regF dst, regF src, flagsRegF0 fcc0) %{
   effect(DEF dst, USE src, KILL fcc0);
   format %{ "FCMPs  fcc0,$src,$src\t! check for NAN\n\t"
@@ -8249,7 +8436,7 @@
   ins_pipe(fcvtF2I);
 %}
 
-instruct convF2I_reg(stackSlotI dst, regF src) %{
+instruct convF2I_stk(stackSlotI dst, regF src) %{
   match(Set dst (ConvF2I src));
   ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST);
   expand %{
@@ -8259,7 +8446,20 @@
   %}
 %}
 
-
+instruct convF2I_reg(iRegI dst, regF src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (ConvF2I src));
+  ins_cost(DEFAULT_COST*2 + BRANCH_COST);
+  expand %{
+    regF tmp;
+    convF2I_helper(tmp, src);
+    MoveF2I_reg_reg(dst, tmp);
+  %}
+%}
+
+
+// Convert a float to a long in a float register.
+// If the float is a NAN, stuff a zero in instead.
 instruct convF2L_helper(regD dst, regF src, flagsRegF0 fcc0) %{
   effect(DEF dst, USE src, KILL fcc0);
   format %{ "FCMPs  fcc0,$src,$src\t! check for NAN\n\t"
@@ -8272,8 +8472,7 @@
   ins_pipe(fcvtF2L);
 %}
 
-// Float to Long conversion
-instruct convF2L_reg(stackSlotL dst, regF src) %{
+instruct convF2L_stk(stackSlotL dst, regF src) %{
   match(Set dst (ConvF2L src));
   ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST);
   expand %{
@@ -8283,6 +8482,17 @@
   %}
 %}
 
+instruct convF2L_reg(iRegL dst, regF src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (ConvF2L src));
+  ins_cost(DEFAULT_COST*2 + BRANCH_COST);
+  expand %{
+    regD tmp;
+    convF2L_helper(tmp, src);
+    MoveD2L_reg_reg(dst, tmp);
+  %}
+%}
+
 
 instruct convI2D_helper(regD dst, regF tmp) %{
   effect(USE tmp, DEF dst);
@@ -8292,17 +8502,27 @@
   ins_pipe(fcvtI2D);
 %}
 
-instruct convI2D_reg(stackSlotI src, regD dst) %{
+instruct convI2D_stk(stackSlotI src, regD dst) %{
   match(Set dst (ConvI2D src));
   ins_cost(DEFAULT_COST + MEMORY_REF_COST);
   expand %{
     regF tmp;
-    stkI_to_regF( tmp, src);
-    convI2D_helper( dst, tmp);
-  %}
-%}
-
-instruct convI2D_mem( regD_low dst, memory mem ) %{
+    stkI_to_regF(tmp, src);
+    convI2D_helper(dst, tmp);
+  %}
+%}
+
+instruct convI2D_reg(regD_low dst, iRegI src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (ConvI2D src));
+  expand %{
+    regF tmp;
+    MoveI2F_reg_reg(tmp, src);
+    convI2D_helper(dst, tmp);
+  %}
+%}
+
+instruct convI2D_mem(regD_low dst, memory mem) %{
   match(Set dst (ConvI2D (LoadI mem)));
   ins_cost(DEFAULT_COST + MEMORY_REF_COST);
   size(8);
@@ -8322,7 +8542,7 @@
   ins_pipe(fcvtI2F);
 %}
 
-instruct convI2F_reg( regF dst, stackSlotI src ) %{
+instruct convI2F_stk(regF dst, stackSlotI src) %{
   match(Set dst (ConvI2F src));
   ins_cost(DEFAULT_COST + MEMORY_REF_COST);
   expand %{
@@ -8332,6 +8552,17 @@
   %}
 %}
 
+instruct convI2F_reg(regF dst, iRegI src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (ConvI2F src));
+  ins_cost(DEFAULT_COST);
+  expand %{
+    regF tmp;
+    MoveI2F_reg_reg(tmp, src);
+    convI2F_helper(dst, tmp);
+  %}
+%}
+
 instruct convI2F_mem( regF dst, memory mem ) %{
   match(Set dst (ConvI2F (LoadI mem)));
   ins_cost(DEFAULT_COST + MEMORY_REF_COST);
@@ -8373,102 +8604,6 @@
   ins_pipe(ialu_reg_reg);
 %}
 
-instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{
-  match(Set dst (MoveF2I src));
-  effect(DEF dst, USE src);
-  ins_cost(MEMORY_REF_COST);
-
-  size(4);
-  format %{ "LDUW   $src,$dst\t! MoveF2I" %}
-  opcode(Assembler::lduw_op3);
-  ins_encode(simple_form3_mem_reg( src, dst ) );
-  ins_pipe(iload_mem);
-%}
-
-instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{
-  match(Set dst (MoveI2F src));
-  effect(DEF dst, USE src);
-  ins_cost(MEMORY_REF_COST);
-
-  size(4);
-  format %{ "LDF    $src,$dst\t! MoveI2F" %}
-  opcode(Assembler::ldf_op3);
-  ins_encode(simple_form3_mem_reg(src, dst));
-  ins_pipe(floadF_stk);
-%}
-
-instruct MoveD2L_stack_reg(iRegL dst, stackSlotD src) %{
-  match(Set dst (MoveD2L src));
-  effect(DEF dst, USE src);
-  ins_cost(MEMORY_REF_COST);
-
-  size(4);
-  format %{ "LDX    $src,$dst\t! MoveD2L" %}
-  opcode(Assembler::ldx_op3);
-  ins_encode(simple_form3_mem_reg( src, dst ) );
-  ins_pipe(iload_mem);
-%}
-
-instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{
-  match(Set dst (MoveL2D src));
-  effect(DEF dst, USE src);
-  ins_cost(MEMORY_REF_COST);
-
-  size(4);
-  format %{ "LDDF   $src,$dst\t! MoveL2D" %}
-  opcode(Assembler::lddf_op3);
-  ins_encode(simple_form3_mem_reg(src, dst));
-  ins_pipe(floadD_stk);
-%}
-
-instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{
-  match(Set dst (MoveF2I src));
-  effect(DEF dst, USE src);
-  ins_cost(MEMORY_REF_COST);
-
-  size(4);
-  format %{ "STF   $src,$dst\t!MoveF2I" %}
-  opcode(Assembler::stf_op3);
-  ins_encode(simple_form3_mem_reg(dst, src));
-  ins_pipe(fstoreF_stk_reg);
-%}
-
-instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{
-  match(Set dst (MoveI2F src));
-  effect(DEF dst, USE src);
-  ins_cost(MEMORY_REF_COST);
-
-  size(4);
-  format %{ "STW    $src,$dst\t!MoveI2F" %}
-  opcode(Assembler::stw_op3);
-  ins_encode(simple_form3_mem_reg( dst, src ) );
-  ins_pipe(istore_mem_reg);
-%}
-
-instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{
-  match(Set dst (MoveD2L src));
-  effect(DEF dst, USE src);
-  ins_cost(MEMORY_REF_COST);
-
-  size(4);
-  format %{ "STDF   $src,$dst\t!MoveD2L" %}
-  opcode(Assembler::stdf_op3);
-  ins_encode(simple_form3_mem_reg(dst, src));
-  ins_pipe(fstoreD_stk_reg);
-%}
-
-instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{
-  match(Set dst (MoveL2D src));
-  effect(DEF dst, USE src);
-  ins_cost(MEMORY_REF_COST);
-
-  size(4);
-  format %{ "STX    $src,$dst\t!MoveL2D" %}
-  opcode(Assembler::stx_op3);
-  ins_encode(simple_form3_mem_reg( dst, src ) );
-  ins_pipe(istore_mem_reg);
-%}
-
 
 //-----------
 // Long to Double conversion using V8 opcodes.
@@ -8589,7 +8724,7 @@
   ins_pipe(fcvtL2D);
 %}
 
-instruct convL2D_reg_fast_fxtof(regD dst, stackSlotL src) %{
+instruct convL2D_stk_fast_fxtof(regD dst, stackSlotL src) %{
   predicate(VM_Version::has_fast_fxtof());
   match(Set dst (ConvL2D src));
   ins_cost(DEFAULT_COST + 3 * MEMORY_REF_COST);
@@ -8600,10 +8735,15 @@
   %}
 %}
 
-//-----------
-// Long to Float conversion using V8 opcodes.
-// Still useful because cheetah traps and becomes
-// amazingly slow for some common numbers.
+instruct convL2D_reg(regD dst, iRegL src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (ConvL2D src));
+  expand %{
+    regD tmp;
+    MoveL2D_reg_reg(tmp, src);
+    convL2D_helper(dst, tmp);
+  %}
+%}
 
 // Long to Float conversion using fast fxtof
 instruct convL2F_helper(regF dst, regD tmp) %{
@@ -8615,7 +8755,7 @@
   ins_pipe(fcvtL2F);
 %}
 
-instruct convL2F_reg_fast_fxtof(regF dst, stackSlotL src) %{
+instruct convL2F_stk_fast_fxtof(regF dst, stackSlotL src) %{
   match(Set dst (ConvL2F src));
   ins_cost(DEFAULT_COST + MEMORY_REF_COST);
   expand %{
@@ -8624,6 +8764,18 @@
     convL2F_helper(dst, tmp);
   %}
 %}
+
+instruct convL2F_reg(regF dst, iRegL src) %{
+  predicate(UseVIS >= 3);
+  match(Set dst (ConvL2F src));
+  ins_cost(DEFAULT_COST);
+  expand %{
+    regD tmp;
+    MoveL2D_reg_reg(tmp, src);
+    convL2F_helper(dst, tmp);
+  %}
+%}
+
 //-----------
 
 instruct convL2I_reg(iRegI dst, iRegL src) %{
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -144,6 +144,18 @@
   // buf is started with ", " or is empty
   _features_str = strdup(strlen(buf) > 2 ? buf + 2 : buf);
 
+  // UseVIS is set to the smallest of what hardware supports and what
+  // the command line requires.  I.e., you cannot set UseVIS to 3 on
+  // older UltraSparc which do not support it.
+  if (UseVIS > 3) UseVIS=3;
+  if (UseVIS < 0) UseVIS=0;
+  if (!has_vis3()) // Drop to 2 if no VIS3 support
+    UseVIS = MIN2((intx)2,UseVIS);
+  if (!has_vis2()) // Drop to 1 if no VIS2 support
+    UseVIS = MIN2((intx)1,UseVIS);
+  if (!has_vis1()) // Drop to 0 if no VIS1 support
+    UseVIS = 0;
+
 #ifndef PRODUCT
   if (PrintMiscellaneous && Verbose) {
     tty->print("Allocation: ");
--- a/src/cpu/x86/vm/interp_masm_x86_32.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -403,9 +403,9 @@
     // interp_only_mode if these events CAN be enabled.
     get_thread(temp);
     // interp_only is an int, on little endian it is sufficient to test the byte only
-    // Is a cmpl faster (ce
+    // Is a cmpl faster?
     cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0);
-    jcc(Assembler::zero, run_compiled_code);
+    jccb(Assembler::zero, run_compiled_code);
     jmp(Address(method, methodOopDesc::interpreter_entry_offset()));
     bind(run_compiled_code);
   }
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -402,7 +402,7 @@
     // interp_only is an int, on little endian it is sufficient to test the byte only
     // Is a cmpl faster?
     cmpb(Address(r15_thread, JavaThread::interp_only_mode_offset()), 0);
-    jcc(Assembler::zero, run_compiled_code);
+    jccb(Assembler::zero, run_compiled_code);
     jmp(Address(method, methodOopDesc::interpreter_entry_offset()));
     bind(run_compiled_code);
   }
--- a/src/cpu/x86/vm/methodHandles_x86.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/cpu/x86/vm/methodHandles_x86.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -546,6 +546,28 @@
 }
 #endif //ASSERT
 
+void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp) {
+  if (JvmtiExport::can_post_interpreter_events()) {
+    Label run_compiled_code;
+    // JVMTI events, such as single-stepping, are implemented partly by avoiding running
+    // compiled code in threads for which the event is enabled.  Check here for
+    // interp_only_mode if these events CAN be enabled.
+#ifdef _LP64
+    Register rthread = r15_thread;
+#else
+    Register rthread = temp;
+    __ get_thread(rthread);
+#endif
+    // interp_only is an int, on little endian it is sufficient to test the byte only
+    // Is a cmpl faster?
+    __ cmpb(Address(rthread, JavaThread::interp_only_mode_offset()), 0);
+    __ jccb(Assembler::zero, run_compiled_code);
+    __ jmp(Address(method, methodOopDesc::interpreter_entry_offset()));
+    __ bind(run_compiled_code);
+  }
+  __ jmp(Address(method, methodOopDesc::from_interpreted_offset()));
+}
+
 // Code generation
 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
   // rbx: methodOop
@@ -1120,9 +1142,6 @@
   guarantee(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
 
   // some handy addresses
-  Address rbx_method_fie(     rbx,      methodOopDesc::from_interpreted_offset() );
-  Address rbx_method_fce(     rbx,      methodOopDesc::from_compiled_offset() );
-
   Address rcx_mh_vmtarget(    rcx_recv, java_lang_invoke_MethodHandle::vmtarget_offset_in_bytes() );
   Address rcx_dmh_vmindex(    rcx_recv, java_lang_invoke_DirectMethodHandle::vmindex_offset_in_bytes() );
 
@@ -1163,8 +1182,8 @@
       assert(raise_exception_method(), "must be set");
       assert(raise_exception_method()->from_compiled_entry(), "method must be linked");
 
-      const Register rdi_pc = rax;
-      __ pop(rdi_pc);  // caller PC
+      const Register rax_pc = rax;
+      __ pop(rax_pc);  // caller PC
       __ mov(rsp, saved_last_sp);  // cut the stack back to where the caller started
 
       Register rbx_method = rbx_temp;
@@ -1172,11 +1191,15 @@
 
       const int jobject_oop_offset = 0;
       __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset));  // dereference the jobject
-      __ verify_oop(rbx_method);
 
-      NOT_LP64(__ push(rarg2_required));
-      __ push(rdi_pc);         // restore caller PC
-      __ jmp(rbx_method_fce);  // jump to compiled entry
+      __ movptr(rsi, rsp);
+      __ subptr(rsp, 3 * wordSize);
+      __ push(rax_pc);         // restore caller PC
+
+      __ movptr(__ argument_address(constant(2)), rarg0_code);
+      __ movptr(__ argument_address(constant(1)), rarg1_actual);
+      __ movptr(__ argument_address(constant(0)), rarg2_required);
+      jump_from_method_handle(_masm, rbx_method, rax);
     }
     break;
 
@@ -1195,7 +1218,7 @@
         __ null_check(rcx_recv);
         __ verify_oop(rcx_recv);
       }
-      __ jmp(rbx_method_fie);
+      jump_from_method_handle(_masm, rbx_method, rax);
     }
     break;
 
@@ -1228,7 +1251,7 @@
       __ movptr(rbx_method, vtable_entry_addr);
 
       __ verify_oop(rbx_method);
-      __ jmp(rbx_method_fie);
+      jump_from_method_handle(_masm, rbx_method, rax);
     }
     break;
 
@@ -1263,7 +1286,7 @@
                                  no_such_interface);
 
       __ verify_oop(rbx_method);
-      __ jmp(rbx_method_fie);
+      jump_from_method_handle(_masm, rbx_method, rax);
       __ hlt();
 
       __ bind(no_such_interface);
@@ -1311,7 +1334,7 @@
         Register rbx_method = rbx_temp;
         __ load_heap_oop(rbx_method, rcx_mh_vmtarget);
         __ verify_oop(rbx_method);
-        __ jmp(rbx_method_fie);
+        jump_from_method_handle(_masm, rbx_method, rax);
       } else {
         __ load_heap_oop(rcx_recv, rcx_mh_vmtarget);
         __ verify_oop(rcx_recv);
--- a/src/cpu/x86/vm/methodHandles_x86.hpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/cpu/x86/vm/methodHandles_x86.hpp	Thu Aug 11 14:58:29 2011 +0100
@@ -291,6 +291,10 @@
                  "reference is a MH");
   }
 
+  // Similar to InterpreterMacroAssembler::jump_from_interpreted.
+  // Takes care of special dispatch from single stepping too.
+  static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp);
+
   static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
 
   static Register saved_last_sp_register() {
--- a/src/os/linux/vm/os_linux.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/os/linux/vm/os_linux.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -125,6 +125,10 @@
 # include <inttypes.h>
 # include <sys/ioctl.h>
 
+#ifdef AMD64
+#include <asm/vsyscall.h>
+#endif
+
 #define MAX_PATH    (2 * K)
 
 // for timer info max values which include all bits
@@ -2534,7 +2538,7 @@
 }
 
 void os::free_memory(char *addr, size_t bytes) {
-  ::madvise(addr, bytes, MADV_DONTNEED);
+  commit_memory(addr, bytes, false);
 }
 
 void os::numa_make_global(char *addr, size_t bytes) {
@@ -2578,6 +2582,22 @@
   return end;
 }
 
+
+int os::Linux::sched_getcpu_syscall(void) {
+  unsigned int cpu;
+  int retval = -1;
+
+#if defined(IA32)
+  retval = syscall(SYS_getcpu, &cpu, NULL, NULL);
+#elif defined(AMD64)
+  typedef long (*vgetcpu_t)(unsigned int *cpu, unsigned int *node, unsigned long *tcache);
+  vgetcpu_t vgetcpu = (vgetcpu_t)VSYSCALL_ADDR(__NR_vgetcpu);
+  retval = vgetcpu(&cpu, NULL, NULL);
+#endif
+
+  return (retval == -1) ? retval : cpu;
+}
+
 // Something to do with the numa-aware allocator needs these symbols
 extern "C" JNIEXPORT void numa_warn(int number, char *where, ...) { }
 extern "C" JNIEXPORT void numa_error(char *where) { }
@@ -2601,6 +2621,10 @@
   set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t,
                                   dlsym(RTLD_DEFAULT, "sched_getcpu")));
 
+  // If it's not, try a direct syscall.
+  if (sched_getcpu() == -1)
+    set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t, (void*)&sched_getcpu_syscall));
+
   if (sched_getcpu() != -1) { // Does it work?
     void *handle = dlopen("libnuma.so.1", RTLD_LAZY);
     if (handle != NULL) {
--- a/src/os/linux/vm/os_linux.hpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/os/linux/vm/os_linux.hpp	Thu Aug 11 14:58:29 2011 +0100
@@ -263,6 +263,7 @@
   static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; }
   static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; }
   static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; }
+  static int sched_getcpu_syscall(void);
 public:
   static int sched_getcpu()  { return _sched_getcpu != NULL ? _sched_getcpu() : -1; }
   static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) {
--- a/src/share/vm/classfile/javaClasses.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/classfile/javaClasses.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -1019,6 +1019,16 @@
   compute_offset(_ngroups_offset,     k, vmSymbols::ngroups_name(),     vmSymbols::int_signature());
 }
 
+oop java_lang_Throwable::unassigned_stacktrace() {
+  instanceKlass* ik = instanceKlass::cast(SystemDictionary::Throwable_klass());
+  address addr = ik->static_field_addr(static_unassigned_stacktrace_offset);
+  if (UseCompressedOops) {
+    return oopDesc::load_decode_heap_oop((narrowOop *)addr);
+  } else {
+    return oopDesc::load_decode_heap_oop((oop*)addr);
+  }
+}
+
 oop java_lang_Throwable::backtrace(oop throwable) {
   return throwable->obj_field_acquire(backtrace_offset);
 }
@@ -1044,9 +1054,13 @@
 }
 
 
+void java_lang_Throwable::set_stacktrace(oop throwable, oop st_element_array) {
+  throwable->obj_field_put(stackTrace_offset, st_element_array);
+}
+
 void java_lang_Throwable::clear_stacktrace(oop throwable) {
   assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4");
-  throwable->obj_field_put(stackTrace_offset, NULL);
+  set_stacktrace(throwable, NULL);
 }
 
 
@@ -1340,6 +1354,7 @@
   if (JDK_Version::is_gte_jdk14x_version()) {
     // New since 1.4, clear lazily constructed Java level stacktrace if
     // refilling occurs
+    // This is unnecessary in 1.7+ but harmless
     clear_stacktrace(throwable());
   }
 
@@ -1541,6 +1556,15 @@
     // Bail-out for deep stacks
     if (chunk_count >= max_chunks) break;
   }
+
+  // For Java 7+ we support the Throwable immutability protocol defined for Java 7. This support
+  // was missing in 7u0 so in 7u0 there is a workaround in the Throwable class. That workaround
+  // can be removed in a JDK using this JVM version
+  if (JDK_Version::is_gte_jdk17x_version()) {
+      java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace());
+      assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized");
+  }
+
 }
 
 
@@ -2770,6 +2794,7 @@
 int java_lang_Throwable::detailMessage_offset;
 int java_lang_Throwable::cause_offset;
 int java_lang_Throwable::stackTrace_offset;
+int java_lang_Throwable::static_unassigned_stacktrace_offset;
 int java_lang_reflect_AccessibleObject::override_offset;
 int java_lang_reflect_Method::clazz_offset;
 int java_lang_reflect_Method::name_offset;
@@ -2947,6 +2972,7 @@
   java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
   java_lang_Throwable::cause_offset      = java_lang_Throwable::hc_cause_offset      * x + header;
   java_lang_Throwable::stackTrace_offset = java_lang_Throwable::hc_stackTrace_offset * x + header;
+  java_lang_Throwable::static_unassigned_stacktrace_offset = java_lang_Throwable::hc_static_unassigned_stacktrace_offset *  x;
 
   // java_lang_boxing_object
   java_lang_boxing_object::value_offset = java_lang_boxing_object::hc_value_offset + header;
--- a/src/share/vm/classfile/javaClasses.hpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/classfile/javaClasses.hpp	Thu Aug 11 14:58:29 2011 +0100
@@ -393,6 +393,9 @@
     hc_cause_offset         =  2,  // New since 1.4
     hc_stackTrace_offset    =  3   // New since 1.4
   };
+  enum {
+      hc_static_unassigned_stacktrace_offset = 0  // New since 1.7
+  };
   // Trace constants
   enum {
     trace_methods_offset = 0,
@@ -406,6 +409,7 @@
   static int detailMessage_offset;
   static int cause_offset;
   static int stackTrace_offset;
+  static int static_unassigned_stacktrace_offset;
 
   // Printing
   static char* print_stack_element_to_buffer(methodOop method, int bci);
@@ -414,6 +418,9 @@
   static void clear_stacktrace(oop throwable);
   // No stack trace available
   static const char* no_stack_trace_message();
+  // Stacktrace (post JDK 1.7.0 to allow immutability protocol to be followed)
+  static void set_stacktrace(oop throwable, oop st_element_array);
+  static oop unassigned_stacktrace();
 
  public:
   // Backtrace
@@ -438,7 +445,6 @@
   static void allocate_backtrace(Handle throwable, TRAPS);
   // Fill in current stack trace for throwable with preallocated backtrace (no GC)
   static void fill_in_stack_trace_of_preallocated_backtrace(Handle throwable);
-
   // Fill in current stack trace, can cause GC
   static void fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS);
   static void fill_in_stack_trace(Handle throwable, methodHandle method = methodHandle());
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -1901,12 +1901,27 @@
   PermanentGenerationSpec* pgs = collector_policy()->permanent_generation();
   // Includes the perm-gen.
 
-  const size_t total_reserved = max_byte_size + pgs->max_size();
+  // When compressed oops are enabled, the preferred heap base
+  // is calculated by subtracting the requested size from the
+  // 32Gb boundary and using the result as the base address for
+  // heap reservation. If the requested size is not aligned to
+  // HeapRegion::GrainBytes (i.e. the alignment that is passed
+  // into the ReservedHeapSpace constructor) then the actual
+  // base of the reserved heap may end up differing from the
+  // address that was requested (i.e. the preferred heap base).
+  // If this happens then we could end up using a non-optimal
+  // compressed oops mode.
+
+  // Since max_byte_size is aligned to the size of a heap region (checked
+  // above), we also need to align the perm gen size as it might not be.
+  const size_t total_reserved = max_byte_size +
+                                align_size_up(pgs->max_size(), HeapRegion::GrainBytes);
+  Universe::check_alignment(total_reserved, HeapRegion::GrainBytes, "g1 heap and perm");
+
   char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
 
-  ReservedSpace heap_rs(max_byte_size + pgs->max_size(),
-                        HeapRegion::GrainBytes,
-                        UseLargePages, addr);
+  ReservedHeapSpace heap_rs(total_reserved, HeapRegion::GrainBytes,
+                            UseLargePages, addr);
 
   if (UseCompressedOops) {
     if (addr != NULL && !heap_rs.is_reserved()) {
@@ -1914,14 +1929,17 @@
       // region is taken already, for example, by 'java' launcher.
       // Try again to reserver heap higher.
       addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
-      ReservedSpace heap_rs0(total_reserved, HeapRegion::GrainBytes,
-                             UseLargePages, addr);
+
+      ReservedHeapSpace heap_rs0(total_reserved, HeapRegion::GrainBytes,
+                                 UseLargePages, addr);
+
       if (addr != NULL && !heap_rs0.is_reserved()) {
         // Failed to reserve at specified address again - give up.
         addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
         assert(addr == NULL, "");
-        ReservedSpace heap_rs1(total_reserved, HeapRegion::GrainBytes,
-                               UseLargePages, addr);
+
+        ReservedHeapSpace heap_rs1(total_reserved, HeapRegion::GrainBytes,
+                                   UseLargePages, addr);
         heap_rs = heap_rs1;
       } else {
         heap_rs = heap_rs0;
@@ -4834,6 +4852,7 @@
                                   scan_perm_cl,
                                   i);
     pss.end_strong_roots();
+
     {
       double start = os::elapsedTime();
       G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator);
@@ -4890,41 +4909,43 @@
                        &eager_scan_code_roots,
                        &buf_scan_perm);
 
-  // Finish up any enqueued closure apps.
-  buf_scan_non_heap_roots.done();
-  buf_scan_perm.done();
-  double ext_roots_end = os::elapsedTime();
-  g1_policy()->reset_obj_copy_time(worker_i);
-  double obj_copy_time_sec =
-    buf_scan_non_heap_roots.closure_app_seconds() +
-    buf_scan_perm.closure_app_seconds();
-  g1_policy()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0);
-  double ext_root_time_ms =
-    ((ext_roots_end - ext_roots_start) - obj_copy_time_sec) * 1000.0;
-  g1_policy()->record_ext_root_scan_time(worker_i, ext_root_time_ms);
-
-  // Scan strong roots in mark stack.
-  if (!_process_strong_tasks->is_task_claimed(G1H_PS_mark_stack_oops_do)) {
-    concurrent_mark()->oops_do(scan_non_heap_roots);
-  }
-  double mark_stack_scan_ms = (os::elapsedTime() - ext_roots_end) * 1000.0;
-  g1_policy()->record_mark_stack_scan_time(worker_i, mark_stack_scan_ms);
-
-  // XXX What should this be doing in the parallel case?
-  g1_policy()->record_collection_pause_end_CH_strong_roots();
-  // Now scan the complement of the collection set.
-  if (scan_rs != NULL) {
-    g1_rem_set()->oops_into_collection_set_do(scan_rs, worker_i);
-  }
-  // Finish with the ref_processor roots.
+  // Now the ref_processor roots.
   if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) {
     // We need to treat the discovered reference lists as roots and
     // keep entries (which are added by the marking threads) on them
     // live until they can be processed at the end of marking.
-    ref_processor()->weak_oops_do(scan_non_heap_roots);
-    ref_processor()->oops_do(scan_non_heap_roots);
-  }
-  g1_policy()->record_collection_pause_end_G1_strong_roots();
+    ref_processor()->weak_oops_do(&buf_scan_non_heap_roots);
+    ref_processor()->oops_do(&buf_scan_non_heap_roots);
+  }
+
+  // Finish up any enqueued closure apps (attributed as object copy time).
+  buf_scan_non_heap_roots.done();
+  buf_scan_perm.done();
+
+  double ext_roots_end = os::elapsedTime();
+
+  g1_policy()->reset_obj_copy_time(worker_i);
+  double obj_copy_time_sec = buf_scan_perm.closure_app_seconds() +
+                                buf_scan_non_heap_roots.closure_app_seconds();
+  g1_policy()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0);
+
+  double ext_root_time_ms =
+    ((ext_roots_end - ext_roots_start) - obj_copy_time_sec) * 1000.0;
+
+  g1_policy()->record_ext_root_scan_time(worker_i, ext_root_time_ms);
+
+  // Scan strong roots in mark stack.
+  if (!_process_strong_tasks->is_task_claimed(G1H_PS_mark_stack_oops_do)) {
+    concurrent_mark()->oops_do(scan_non_heap_roots);
+  }
+  double mark_stack_scan_ms = (os::elapsedTime() - ext_roots_end) * 1000.0;
+  g1_policy()->record_mark_stack_scan_time(worker_i, mark_stack_scan_ms);
+
+  // Now scan the complement of the collection set.
+  if (scan_rs != NULL) {
+    g1_rem_set()->oops_into_collection_set_do(scan_rs, worker_i);
+  }
+
   _process_strong_tasks->all_tasks_completed();
 }
 
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Aug 11 14:58:29 2011 +0100
@@ -393,8 +393,7 @@
   // Perform finalization stuff on all allocation regions.
   void retire_all_alloc_regions();
 
-  // The number of regions allocated to hold humongous objects.
-  int         _num_humongous_regions;
+  // The young region list.
   YoungList*  _young_list;
 
   // The current policy object for the collector.
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -134,13 +134,10 @@
 
 G1CollectorPolicy::G1CollectorPolicy() :
   _parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads()
-    ? ParallelGCThreads : 1),
-
+                        ? ParallelGCThreads : 1),
 
   _n_pauses(0),
-  _recent_CH_strong_roots_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
-  _recent_G1_strong_roots_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
-  _recent_evac_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
+  _recent_rs_scan_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
   _recent_pause_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
   _recent_rs_sizes(new TruncatedSeq(NumPrevPausesForHeuristics)),
   _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
@@ -1050,18 +1047,6 @@
 void G1CollectorPolicy::record_concurrent_pause_end() {
 }
 
-void G1CollectorPolicy::record_collection_pause_end_CH_strong_roots() {
-  _cur_CH_strong_roots_end_sec = os::elapsedTime();
-  _cur_CH_strong_roots_dur_ms =
-    (_cur_CH_strong_roots_end_sec - _cur_collection_start_sec) * 1000.0;
-}
-
-void G1CollectorPolicy::record_collection_pause_end_G1_strong_roots() {
-  _cur_G1_strong_roots_end_sec = os::elapsedTime();
-  _cur_G1_strong_roots_dur_ms =
-    (_cur_G1_strong_roots_end_sec - _cur_CH_strong_roots_end_sec) * 1000.0;
-}
-
 template<class T>
 T sum_of(T* sum_arr, int start, int n, int N) {
   T sum = (T)0;
@@ -1183,7 +1168,6 @@
   double end_time_sec = os::elapsedTime();
   double elapsed_ms = _last_pause_time_ms;
   bool parallel = G1CollectedHeap::use_parallel_gc_threads();
-  double evac_ms = (end_time_sec - _cur_G1_strong_roots_end_sec) * 1000.0;
   size_t rs_size =
     _cur_collection_pause_used_regions_at_start - collection_set_size();
   size_t cur_used_bytes = _g1->used();
@@ -1256,14 +1240,52 @@
 
   _n_pauses++;
 
+  double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
+  double mark_stack_scan_time = avg_value(_par_last_mark_stack_scan_times_ms);
+  double update_rs_time = avg_value(_par_last_update_rs_times_ms);
+  double update_rs_processed_buffers =
+    sum_of_values(_par_last_update_rs_processed_buffers);
+  double scan_rs_time = avg_value(_par_last_scan_rs_times_ms);
+  double obj_copy_time = avg_value(_par_last_obj_copy_times_ms);
+  double termination_time = avg_value(_par_last_termination_times_ms);
+
+  double parallel_known_time = update_rs_time +
+                               ext_root_scan_time +
+                               mark_stack_scan_time +
+                               scan_rs_time +
+                               obj_copy_time +
+                               termination_time;
+
+  double parallel_other_time = _cur_collection_par_time_ms - parallel_known_time;
+
+  PauseSummary* summary = _summary;
+
   if (update_stats) {
-    _recent_CH_strong_roots_times_ms->add(_cur_CH_strong_roots_dur_ms);
-    _recent_G1_strong_roots_times_ms->add(_cur_G1_strong_roots_dur_ms);
-    _recent_evac_times_ms->add(evac_ms);
+    _recent_rs_scan_times_ms->add(scan_rs_time);
     _recent_pause_times_ms->add(elapsed_ms);
-
     _recent_rs_sizes->add(rs_size);
 
+    MainBodySummary* body_summary = summary->main_body_summary();
+    guarantee(body_summary != NULL, "should not be null!");
+
+    if (_satb_drain_time_set)
+      body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms);
+    else
+      body_summary->record_satb_drain_time_ms(0.0);
+
+    body_summary->record_ext_root_scan_time_ms(ext_root_scan_time);
+    body_summary->record_mark_stack_scan_time_ms(mark_stack_scan_time);
+    body_summary->record_update_rs_time_ms(update_rs_time);
+    body_summary->record_scan_rs_time_ms(scan_rs_time);
+    body_summary->record_obj_copy_time_ms(obj_copy_time);
+    if (parallel) {
+      body_summary->record_parallel_time_ms(_cur_collection_par_time_ms);
+      body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms);
+      body_summary->record_termination_time_ms(termination_time);
+      body_summary->record_parallel_other_time_ms(parallel_other_time);
+    }
+    body_summary->record_mark_closure_time_ms(_mark_closure_time_ms);
+
     // We exempt parallel collection from this check because Alloc Buffer
     // fragmentation can produce negative collections.  Same with evac
     // failure.
@@ -1328,56 +1350,12 @@
     gclog_or_tty->print_cr("   Recording collection pause(%d)", _n_pauses);
   }
 
-  PauseSummary* summary = _summary;
-
-  double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
-  double mark_stack_scan_time = avg_value(_par_last_mark_stack_scan_times_ms);
-  double update_rs_time = avg_value(_par_last_update_rs_times_ms);
-  double update_rs_processed_buffers =
-    sum_of_values(_par_last_update_rs_processed_buffers);
-  double scan_rs_time = avg_value(_par_last_scan_rs_times_ms);
-  double obj_copy_time = avg_value(_par_last_obj_copy_times_ms);
-  double termination_time = avg_value(_par_last_termination_times_ms);
-
-  double parallel_other_time = _cur_collection_par_time_ms -
-    (update_rs_time + ext_root_scan_time + mark_stack_scan_time +
-     scan_rs_time + obj_copy_time + termination_time);
-  if (update_stats) {
-    MainBodySummary* body_summary = summary->main_body_summary();
-    guarantee(body_summary != NULL, "should not be null!");
-
-    if (_satb_drain_time_set)
-      body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms);
-    else
-      body_summary->record_satb_drain_time_ms(0.0);
-    body_summary->record_ext_root_scan_time_ms(ext_root_scan_time);
-    body_summary->record_mark_stack_scan_time_ms(mark_stack_scan_time);
-    body_summary->record_update_rs_time_ms(update_rs_time);
-    body_summary->record_scan_rs_time_ms(scan_rs_time);
-    body_summary->record_obj_copy_time_ms(obj_copy_time);
-    if (parallel) {
-      body_summary->record_parallel_time_ms(_cur_collection_par_time_ms);
-      body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms);
-      body_summary->record_termination_time_ms(termination_time);
-      body_summary->record_parallel_other_time_ms(parallel_other_time);
-    }
-    body_summary->record_mark_closure_time_ms(_mark_closure_time_ms);
-  }
-
   if (G1PolicyVerbose > 1) {
     gclog_or_tty->print_cr("      ET: %10.6f ms           (avg: %10.6f ms)\n"
-                           "        CH Strong: %10.6f ms    (avg: %10.6f ms)\n"
-                           "        G1 Strong: %10.6f ms    (avg: %10.6f ms)\n"
-                           "        Evac:      %10.6f ms    (avg: %10.6f ms)\n"
                            "       ET-RS:  %10.6f ms      (avg: %10.6f ms)\n"
                            "      |RS|: " SIZE_FORMAT,
                            elapsed_ms, recent_avg_time_for_pauses_ms(),
-                           _cur_CH_strong_roots_dur_ms, recent_avg_time_for_CH_strong_ms(),
-                           _cur_G1_strong_roots_dur_ms, recent_avg_time_for_G1_strong_ms(),
-                           evac_ms, recent_avg_time_for_evac_ms(),
-                           scan_rs_time,
-                           recent_avg_time_for_pauses_ms() -
-                           recent_avg_time_for_G1_strong_ms(),
+                           scan_rs_time, recent_avg_time_for_rs_scan_ms(),
                            rs_size);
 
     gclog_or_tty->print_cr("       Used at start: " SIZE_FORMAT"K"
@@ -1438,7 +1416,7 @@
       }
       print_par_stats(2, "GC Worker Times", _par_last_gc_worker_times_ms);
 
-      print_stats(2, "Other", parallel_other_time);
+      print_stats(2, "Parallel Other", parallel_other_time);
       print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
     } else {
       print_stats(1, "Update RS", update_rs_time);
@@ -1967,38 +1945,27 @@
 }
 
 double G1CollectorPolicy::recent_avg_time_for_pauses_ms() {
-  if (_recent_pause_times_ms->num() == 0) return (double) MaxGCPauseMillis;
-  else return _recent_pause_times_ms->avg();
+  if (_recent_pause_times_ms->num() == 0) {
+    return (double) MaxGCPauseMillis;
+  }
+  return _recent_pause_times_ms->avg();
 }
 
-double G1CollectorPolicy::recent_avg_time_for_CH_strong_ms() {
-  if (_recent_CH_strong_roots_times_ms->num() == 0)
+double G1CollectorPolicy::recent_avg_time_for_rs_scan_ms() {
+  if (_recent_rs_scan_times_ms->num() == 0) {
     return (double)MaxGCPauseMillis/3.0;
-  else return _recent_CH_strong_roots_times_ms->avg();
+  }
+  return _recent_rs_scan_times_ms->avg();
 }
 
-double G1CollectorPolicy::recent_avg_time_for_G1_strong_ms() {
-  if (_recent_G1_strong_roots_times_ms->num() == 0)
-    return (double)MaxGCPauseMillis/3.0;
-  else return _recent_G1_strong_roots_times_ms->avg();
-}
-
-double G1CollectorPolicy::recent_avg_time_for_evac_ms() {
-  if (_recent_evac_times_ms->num() == 0) return (double)MaxGCPauseMillis/3.0;
-  else return _recent_evac_times_ms->avg();
-}
-
 int G1CollectorPolicy::number_of_recent_gcs() {
-  assert(_recent_CH_strong_roots_times_ms->num() ==
-         _recent_G1_strong_roots_times_ms->num(), "Sequence out of sync");
-  assert(_recent_G1_strong_roots_times_ms->num() ==
-         _recent_evac_times_ms->num(), "Sequence out of sync");
-  assert(_recent_evac_times_ms->num() ==
+  assert(_recent_rs_scan_times_ms->num() ==
          _recent_pause_times_ms->num(), "Sequence out of sync");
   assert(_recent_pause_times_ms->num() ==
          _recent_CS_bytes_used_before->num(), "Sequence out of sync");
   assert(_recent_CS_bytes_used_before->num() ==
          _recent_CS_bytes_surviving->num(), "Sequence out of sync");
+
   return _recent_pause_times_ms->num();
 }
 
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Thu Aug 11 14:58:29 2011 +0100
@@ -129,15 +129,9 @@
   jlong  _num_cc_clears;                // number of times the card count cache has been cleared
 #endif
 
-  double _cur_CH_strong_roots_end_sec;
-  double _cur_CH_strong_roots_dur_ms;
-  double _cur_G1_strong_roots_end_sec;
-  double _cur_G1_strong_roots_dur_ms;
+  // Statistics for recent GC pauses.  See below for how indexed.
+  TruncatedSeq* _recent_rs_scan_times_ms;
 
-  // Statistics for recent GC pauses.  See below for how indexed.
-  TruncatedSeq* _recent_CH_strong_roots_times_ms;
-  TruncatedSeq* _recent_G1_strong_roots_times_ms;
-  TruncatedSeq* _recent_evac_times_ms;
   // These exclude marking times.
   TruncatedSeq* _recent_pause_times_ms;
   TruncatedSeq* _recent_gc_times_ms;
@@ -692,17 +686,11 @@
   // The average time in ms per collection pause, averaged over recent pauses.
   double recent_avg_time_for_pauses_ms();
 
-  // The average time in ms for processing CollectedHeap strong roots, per
-  // collection pause, averaged over recent pauses.
-  double recent_avg_time_for_CH_strong_ms();
-
-  // The average time in ms for processing the G1 remembered set, per
-  // pause, averaged over recent pauses.
-  double recent_avg_time_for_G1_strong_ms();
-
-  // The average time in ms for "evacuating followers", per pause, averaged
-  // over recent pauses.
-  double recent_avg_time_for_evac_ms();
+  // The average time in ms for RS scanning, per pause, averaged
+  // over recent pauses. (Note the RS scanning time for a pause
+  // is itself an average of the RS scanning time for each worker
+  // thread.)
+  double recent_avg_time_for_rs_scan_ms();
 
   // The number of "recent" GCs recorded in the number sequences
   int number_of_recent_gcs();
@@ -887,9 +875,6 @@
   virtual void record_concurrent_pause();
   virtual void record_concurrent_pause_end();
 
-  virtual void record_collection_pause_end_CH_strong_roots();
-  virtual void record_collection_pause_end_G1_strong_roots();
-
   virtual void record_collection_pause_end();
   void print_heap_transition();
 
--- a/src/share/vm/opto/parse3.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/opto/parse3.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -417,17 +417,10 @@
 
   // Note:  Array classes are always initialized; no is_initialized check.
 
-  enum { MAX_DIMENSION = 5 };
-  if (ndimensions > MAX_DIMENSION || ndimensions <= 0) {
-    uncommon_trap(Deoptimization::Reason_unhandled,
-                  Deoptimization::Action_none);
-    return;
-  }
-
   kill_dead_locals();
 
   // get the lengths from the stack (first dimension is on top)
-  Node* length[MAX_DIMENSION+1];
+  Node** length = NEW_RESOURCE_ARRAY(Node*, ndimensions + 1);
   length[ndimensions] = NULL;  // terminating null for make_runtime_call
   int j;
   for (j = ndimensions-1; j >= 0 ; j--) length[j] = pop();
@@ -470,20 +463,43 @@
 
   address fun = NULL;
   switch (ndimensions) {
-  //case 1: Actually, there is no case 1.  It's handled by new_array.
+  case 1: ShouldNotReachHere(); break;
   case 2: fun = OptoRuntime::multianewarray2_Java(); break;
   case 3: fun = OptoRuntime::multianewarray3_Java(); break;
   case 4: fun = OptoRuntime::multianewarray4_Java(); break;
   case 5: fun = OptoRuntime::multianewarray5_Java(); break;
-  default: ShouldNotReachHere();
   };
+  Node* c = NULL;
 
-  Node* c = make_runtime_call(RC_NO_LEAF | RC_NO_IO,
-                              OptoRuntime::multianewarray_Type(ndimensions),
-                              fun, NULL, TypeRawPtr::BOTTOM,
-                              makecon(TypeKlassPtr::make(array_klass)),
-                              length[0], length[1], length[2],
-                              length[3], length[4]);
+  if (fun != NULL) {
+    c = make_runtime_call(RC_NO_LEAF | RC_NO_IO,
+                          OptoRuntime::multianewarray_Type(ndimensions),
+                          fun, NULL, TypeRawPtr::BOTTOM,
+                          makecon(TypeKlassPtr::make(array_klass)),
+                          length[0], length[1], length[2],
+                          length[3], length[4]);
+  } else {
+    // Create a java array for dimension sizes
+    Node* dims = NULL;
+    { PreserveReexecuteState preexecs(this);
+      _sp += ndimensions;
+      Node* dims_array_klass = makecon(TypeKlassPtr::make(ciArrayKlass::make(ciType::make(T_INT))));
+      dims = new_array(dims_array_klass, intcon(ndimensions), 0);
+
+      // Fill-in it with values
+      for (j = 0; j < ndimensions; j++) {
+        Node *dims_elem = array_element_address(dims, intcon(j), T_INT);
+        store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS);
+      }
+    }
+
+    c = make_runtime_call(RC_NO_LEAF | RC_NO_IO,
+                          OptoRuntime::multianewarrayN_Type(),
+                          OptoRuntime::multianewarrayN_Java(), NULL, TypeRawPtr::BOTTOM,
+                          makecon(TypeKlassPtr::make(array_klass)),
+                          dims);
+  }
+
   Node* res = _gvn.transform(new (C, 1) ProjNode(c, TypeFunc::Parms));
 
   const Type* type = TypeOopPtr::make_from_klass_raw(array_klass);
@@ -496,7 +512,7 @@
   if (ltype != NULL)
     type = type->is_aryptr()->cast_to_size(ltype);
 
-  // We cannot sharpen the nested sub-arrays, since the top level is mutable.
+    // We cannot sharpen the nested sub-arrays, since the top level is mutable.
 
   Node* cast = _gvn.transform( new (C, 2) CheckCastPPNode(control(), res, type) );
   push(cast);
--- a/src/share/vm/opto/runtime.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/opto/runtime.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -106,6 +106,7 @@
 address OptoRuntime::_multianewarray3_Java                        = NULL;
 address OptoRuntime::_multianewarray4_Java                        = NULL;
 address OptoRuntime::_multianewarray5_Java                        = NULL;
+address OptoRuntime::_multianewarrayN_Java                        = NULL;
 address OptoRuntime::_g1_wb_pre_Java                              = NULL;
 address OptoRuntime::_g1_wb_post_Java                             = NULL;
 address OptoRuntime::_vtable_must_compile_Java                    = NULL;
@@ -154,6 +155,7 @@
   gen(env, _multianewarray3_Java           , multianewarray3_Type         , multianewarray3_C               ,    0 , true , false, false);
   gen(env, _multianewarray4_Java           , multianewarray4_Type         , multianewarray4_C               ,    0 , true , false, false);
   gen(env, _multianewarray5_Java           , multianewarray5_Type         , multianewarray5_C               ,    0 , true , false, false);
+  gen(env, _multianewarrayN_Java           , multianewarrayN_Type         , multianewarrayN_C               ,    0 , true , false, false);
   gen(env, _g1_wb_pre_Java                 , g1_wb_pre_Type               , SharedRuntime::g1_wb_pre        ,    0 , false, false, false);
   gen(env, _g1_wb_post_Java                , g1_wb_post_Type              , SharedRuntime::g1_wb_post       ,    0 , false, false, false);
   gen(env, _complete_monitor_locking_Java  , complete_monitor_enter_Type  , SharedRuntime::complete_monitor_locking_C      ,    0 , false, false, false);
@@ -374,6 +376,24 @@
   thread->set_vm_result(obj);
 JRT_END
 
+JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(klassOopDesc* elem_type, arrayOopDesc* dims, JavaThread *thread))
+  assert(check_compiled_frame(thread), "incorrect caller");
+  assert(oop(elem_type)->is_klass(), "not a class");
+  assert(oop(dims)->is_typeArray(), "not an array");
+
+  ResourceMark rm;
+  jint len = dims->length();
+  assert(len > 0, "Dimensions array should contain data");
+  jint *j_dims = typeArrayOop(dims)->int_at_addr(0);
+  jint *c_dims = NEW_RESOURCE_ARRAY(jint, len);
+  Copy::conjoint_jints_atomic(j_dims, c_dims, len);
+
+  oop obj = arrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD);
+  deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION);
+  thread->set_vm_result(obj);
+JRT_END
+
+
 const TypeFunc *OptoRuntime::new_instance_Type() {
   // create input type (domain)
   const Type **fields = TypeTuple::fields(1);
@@ -454,6 +474,21 @@
   return multianewarray_Type(5);
 }
 
+const TypeFunc *OptoRuntime::multianewarrayN_Type() {
+  // create input type (domain)
+  const Type **fields = TypeTuple::fields(2);
+  fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL;   // element klass
+  fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL;   // array of dim sizes
+  const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
+
+  // create result type (range)
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop
+  const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
+
+  return TypeFunc::make(domain, range);
+}
+
 const TypeFunc *OptoRuntime::g1_wb_pre_Type() {
   const Type **fields = TypeTuple::fields(2);
   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
--- a/src/share/vm/opto/runtime.hpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/opto/runtime.hpp	Thu Aug 11 14:58:29 2011 +0100
@@ -118,6 +118,7 @@
   static address _multianewarray3_Java;
   static address _multianewarray4_Java;
   static address _multianewarray5_Java;
+  static address _multianewarrayN_Java;
   static address _g1_wb_pre_Java;
   static address _g1_wb_post_Java;
   static address _vtable_must_compile_Java;
@@ -153,6 +154,7 @@
   static void multianewarray3_C(klassOopDesc* klass, int len1, int len2, int len3, JavaThread *thread);
   static void multianewarray4_C(klassOopDesc* klass, int len1, int len2, int len3, int len4, JavaThread *thread);
   static void multianewarray5_C(klassOopDesc* klass, int len1, int len2, int len3, int len4, int len5, JavaThread *thread);
+  static void multianewarrayN_C(klassOopDesc* klass, arrayOopDesc* dims, JavaThread *thread);
   static void g1_wb_pre_C(oopDesc* orig, JavaThread* thread);
   static void g1_wb_post_C(void* card_addr, JavaThread* thread);
 
@@ -210,6 +212,7 @@
   static address multianewarray3_Java()                  { return _multianewarray3_Java; }
   static address multianewarray4_Java()                  { return _multianewarray4_Java; }
   static address multianewarray5_Java()                  { return _multianewarray5_Java; }
+  static address multianewarrayN_Java()                  { return _multianewarrayN_Java; }
   static address g1_wb_pre_Java()                        { return _g1_wb_pre_Java; }
   static address g1_wb_post_Java()                       { return _g1_wb_post_Java; }
   static address vtable_must_compile_stub()              { return _vtable_must_compile_Java; }
@@ -249,6 +252,7 @@
   static const TypeFunc* multianewarray3_Type(); // multianewarray
   static const TypeFunc* multianewarray4_Type(); // multianewarray
   static const TypeFunc* multianewarray5_Type(); // multianewarray
+  static const TypeFunc* multianewarrayN_Type(); // multianewarray
   static const TypeFunc* g1_wb_pre_Type();
   static const TypeFunc* g1_wb_post_Type();
   static const TypeFunc* complete_monitor_enter_Type();
--- a/src/share/vm/prims/jvmtiTagMap.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/prims/jvmtiTagMap.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -1647,6 +1647,7 @@
   // saved headers
   static GrowableArray<oop>* _saved_oop_stack;
   static GrowableArray<markOop>* _saved_mark_stack;
+  static bool _needs_reset;                  // do we need to reset mark bits?
 
  public:
   static void init();                       // initialize
@@ -1654,10 +1655,14 @@
 
   static inline void mark(oop o);           // mark an object
   static inline bool visited(oop o);        // check if object has been visited
+
+  static inline bool needs_reset()            { return _needs_reset; }
+  static inline void set_needs_reset(bool v)  { _needs_reset = v; }
 };
 
 GrowableArray<oop>* ObjectMarker::_saved_oop_stack = NULL;
 GrowableArray<markOop>* ObjectMarker::_saved_mark_stack = NULL;
+bool ObjectMarker::_needs_reset = true;  // need to reset mark bits by default
 
 // initialize ObjectMarker - prepares for object marking
 void ObjectMarker::init() {
@@ -1680,7 +1685,13 @@
   // iterate over all objects and restore the mark bits to
   // their initial value
   RestoreMarksClosure blk;
-  Universe::heap()->object_iterate(&blk);
+  if (needs_reset()) {
+    Universe::heap()->object_iterate(&blk);
+  } else {
+    // We don't need to reset mark bits on this call, but reset the
+    // flag to the default for the next call.
+    set_needs_reset(true);
+  }
 
   // When sharing is enabled we need to restore the headers of the objects
   // in the readwrite space too.
@@ -3023,7 +3034,8 @@
 }
 
 
-// collects all simple (non-stack) roots.
+// Collects all simple (non-stack) roots except for threads;
+// threads are handled in collect_stack_roots() as an optimization.
 // if there's a heap root callback provided then the callback is
 // invoked for each simple root.
 // if an object reference callback is provided then all simple
@@ -3054,16 +3066,7 @@
     return false;
   }
 
-  // Threads
-  for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) {
-    oop threadObj = thread->threadObj();
-    if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) {
-      bool cont = CallbackInvoker::report_simple_root(JVMTI_HEAP_REFERENCE_THREAD, threadObj);
-      if (!cont) {
-        return false;
-      }
-    }
-  }
+  // threads are now handled in collect_stack_roots()
 
   // Other kinds of roots maintained by HotSpot
   // Many of these won't be visible but others (such as instances of important
@@ -3175,13 +3178,20 @@
 }
 
 
-// collects all stack roots - for each thread it walks the execution
+// Collects the simple roots for all threads and collects all
+// stack roots - for each thread it walks the execution
 // stack to find all references and local JNI refs.
 inline bool VM_HeapWalkOperation::collect_stack_roots() {
   JNILocalRootsClosure blk;
   for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) {
     oop threadObj = thread->threadObj();
     if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) {
+      // Collect the simple root for this thread before we
+      // collect its stack roots
+      if (!CallbackInvoker::report_simple_root(JVMTI_HEAP_REFERENCE_THREAD,
+                                               threadObj)) {
+        return false;
+      }
       if (!collect_stack_roots(thread, &blk)) {
         return false;
       }
@@ -3235,8 +3245,20 @@
 
   // the heap walk starts with an initial object or the heap roots
   if (initial_object().is_null()) {
+    // If either collect_stack_roots() or collect_simple_roots()
+    // returns false at this point, then there are no mark bits
+    // to reset.
+    ObjectMarker::set_needs_reset(false);
+
+    // Calling collect_stack_roots() before collect_simple_roots()
+    // can result in a big performance boost for an agent that is
+    // focused on analyzing references in the thread stacks.
+    if (!collect_stack_roots()) return;
+
     if (!collect_simple_roots()) return;
-    if (!collect_stack_roots()) return;
+
+    // no early return so enable heap traversal to reset the mark bits
+    ObjectMarker::set_needs_reset(true);
   } else {
     visit_stack()->push(initial_object()());
   }
--- a/src/share/vm/runtime/globals.hpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/runtime/globals.hpp	Thu Aug 11 14:58:29 2011 +0100
@@ -501,6 +501,9 @@
   product(intx, UseSSE, 99,                                                 \
           "Highest supported SSE instructions set on x86/x64")              \
                                                                             \
+  product(intx, UseVIS, 99,                                                 \
+          "Highest supported VIS instructions set on Sparc")                \
+                                                                            \
   product(uintx, LargePageSizeInBytes, 0,                                   \
           "Large page size (0 to let VM choose the page size")              \
                                                                             \
--- a/src/share/vm/runtime/virtualspace.cpp	Tue Aug 02 14:37:35 2011 +0100
+++ b/src/share/vm/runtime/virtualspace.cpp	Thu Aug 11 14:58:29 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,7 @@
   assert(len >= required_size, "len too small");
 
   const size_t s = size_t(addr);
-  const size_t beg_ofs = s + prefix_size & suffix_align - 1;
+  const size_t beg_ofs = (s + prefix_size) & (suffix_align - 1);
   const size_t beg_delta = beg_ofs == 0 ? 0 : suffix_align - beg_ofs;
 
   if (len < beg_delta + required_size) {
@@ -113,8 +113,8 @@
     assert(res >= raw, "alignment decreased start addr");
     assert(res + prefix_size + suffix_size <= raw + reserve_size,
            "alignment increased end addr");
-    assert((res & prefix_align - 1) == 0, "bad alignment of prefix");
-    assert((res + prefix_size & suffix_align - 1) == 0,
+    assert((res & (prefix_align - 1)) == 0, "bad alignment of prefix");
+    assert(((res + prefix_size) & (suffix_align - 1)) == 0,
            "bad alignment of suffix");
   }
 #endif
@@ -135,7 +135,7 @@
     assert(UseCompressedOops, "currently requested address used only for compressed oops");
     if (PrintCompressedOopsMode) {
       tty->cr();
-      tty->print_cr("Reserved memory at not requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address);
+      tty->print_cr("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address);
     }
     // OS ignored requested address. Try different address.
     if (special) {
@@ -162,11 +162,11 @@
   assert(prefix_align != 0, "sanity");
   assert(suffix_size != 0, "sanity");
   assert(suffix_align != 0, "sanity");
-  assert((prefix_size & prefix_align - 1) == 0,
+  assert((prefix_size & (prefix_align - 1)) == 0,
     "prefix_size not divisible by prefix_align");
-  assert((suffix_size & suffix_align - 1) == 0,
+  assert((suffix_size & (suffix_align - 1)) == 0,
     "suffix_size not divisible by suffix_align");
-  assert((suffix_align & prefix_align - 1) == 0,
+  assert((suffix_align & (prefix_align - 1)) == 0,
     "suffix_align not divisible by prefix_align");
 
   // Assert that if noaccess_prefix is used, it is the same as prefix_align.
@@ -210,8 +210,8 @@
   if (addr == NULL) return;
 
   // Check whether the result has the needed alignment (unlikely unless
-  // prefix_align == suffix_align).
-  const size_t ofs = size_t(addr) + adjusted_prefix_size & suffix_align - 1;
+  // prefix_align < suffix_align).
+  const size_t ofs = (size_t(addr) + adjusted_prefix_size) & (suffix_align - 1);
   if (ofs != 0) {
     // Wrong alignment.  Release, allocate more space and do manual alignment.
     //
@@ -232,6 +232,15 @@
       addr = reserve_and_align(size + suffix_align, adjusted_prefix_size,
                                prefix_align, suffix_size, suffix_align);
     }
+
+    if (requested_address != 0 &&
+        failed_to_reserve_as_requested(addr, requested_address, size, false)) {
+      // As a result of the alignment constraints, the allocated addr differs
+      // from the requested address. Return back to the caller who can
+      // take remedial action (like try again without a requested address).
+      assert(_base == NULL, "should be");
+      return;
+    }
   }
 
   _base = addr;
@@ -245,13 +254,19 @@
                                const size_t noaccess_prefix,
                                bool executable) {
   const size_t granularity = os::vm_allocation_granularity();
-  assert((size & granularity - 1) == 0,
+  assert((size & (granularity - 1)) == 0,
          "size not aligned to os::vm_allocation_granularity()");
-  assert((alignment & granularity - 1) == 0,
+  assert((alignment & (granularity - 1)) == 0,
          "alignment not aligned to os::vm_allocation_granularity()");
   assert(alignment == 0 || is_power_of_2((intptr_t)alignment),
          "not a power of 2");
 
+  alignment = MAX2(alignment, (size_t)os::vm_page_size());
+
+  // Assert that if noaccess_prefix is used, it is the same as alignment.
+  assert(noaccess_prefix == 0 ||
+         noaccess_prefix == alignment, "noaccess prefix wrong");
+
   _base = NULL;
   _size = 0;
   _special = false;
@@ -282,10 +297,8 @@
         return;
       }
       // Check alignment constraints
-      if (alignment > 0) {
-        assert((uintptr_t) base % alignment == 0,
-               "Large pages returned a non-aligned address");
-      }
+      assert((uintptr_t) base % alignment == 0,
+             "Large pages returned a non-aligned address");
       _special = true;
     } else {
       // failed; try to reserve regular memory below
@@ -321,7 +334,7 @@
     if (base == NULL) return;
 
     // Check alignment constraints
-    if (alignment > 0 && ((size_t)base & alignment - 1) != 0) {
+    if ((((size_t)base + noaccess_prefix) & (alignment - 1)) != 0) {
       // Base not aligned, retry
       if (!os::release_memory(base, size)) fatal("os::release_memory failed");
       // Reserve size large enough to do manual alignment and
@@ -338,12 +351,21 @@
         os::release_memory(extra_base, extra_size);
         base = os::reserve_memory(size, base);
       } while (base == NULL);
+
+      if (requested_address != 0 &&
+          failed_to_reserve_as_requested(base, requested_address, size, false)) {
+        // As a result of the alignment constraints, the allocated base differs
+        // from the requested address. Return back to the caller who can
+        // take remedial action (like try again without a requested address).
+        assert(_base == NULL, "should be");
+        return;
+      }
     }
   }
   // Done
   _base = base;
   _size = size;
-  _alignment = MAX2(alignment, (size_t) os::vm_page_size());
+  _alignment = alignment;
   _noaccess_prefix = noaccess_prefix;
 
   // Assert that if noaccess_prefix is used, it is the same as alignment.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/6990212/Test6990212.java	Thu Aug 11 14:58:29 2011 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6990212
+ * @summary JSR 292 JVMTI MethodEnter hook is not called for JSR 292 bootstrap and target methods
+ *
+ * @run main Test6990212
+ */
+
+import java.lang.invoke.*;
+
+interface intf {
+    public Object target();
+}
+
+public class Test6990212 implements intf {
+    public Object target() {
+        return null;
+    }
+
+    public static void main(String[] args) throws Throwable {
+        // Build an interface invoke and then invoke it on something
+        // that doesn't implement the interface to test the
+        // raiseException path.
+        MethodHandle target = MethodHandles.lookup().findVirtual(intf.class, "target",  MethodType.methodType(Object.class));
+        try {
+            target.invoke(new Object());
+        } catch (ClassCastException cce) {
+            // everything is ok
+            System.out.println("got expected ClassCastException");
+        }
+    }
+}
--- a/test/compiler/7052494/Test7052494.java	Tue Aug 02 14:37:35 2011 +0100
+++ b/test/compiler/7052494/Test7052494.java	Thu Aug 11 14:58:29 2011 +0100
@@ -70,18 +70,24 @@
   }
 
   // Empty loop rolls through MAXINT if i > 0
+
+  static final int limit5 = Integer.MIN_VALUE + 10000;
+
   static int test5(int i) {
     int result = 0;
-    while (i++ != 0) {
+    while (i++ != limit5) {
       result = i*2;
     }
     return result;
   }
 
   // Empty loop rolls through MININT if i < 0
+
+  static final int limit6 = Integer.MAX_VALUE - 10000;
+
   static int test6(int i) {
     int result = 0;
-    while (i-- != 0) {
+    while (i-- != limit6) {
       result = i*2;
     }
     return result;
@@ -92,6 +98,7 @@
     int[] arr = new int[8];
     int[] ar3 = { 0, 0, 4, 6, 8, 10, 0, 0 };
     int[] ar4 = { 0, 0, 0, -10, -8, -6, -4, 0 };
+    System.out.println("test1");
     for (int i = 0; i < 11000; i++) {
       int k = test1(1, 10);
       if (k != 10) {
@@ -100,6 +107,7 @@
         break;
       }
     }
+    System.out.println("test2");
     for (int i = 0; i < 11000; i++) {
       int k = test2(-1, -10);
       if (k != -10) {
@@ -108,6 +116,7 @@
         break;
       }
     }
+    System.out.println("test3");
     for (int i = 0; i < 11000; i++) {
       java.util.Arrays.fill(arr, 0);
       test3(1, 10, arr);
@@ -124,6 +133,7 @@
         break;
       }
     }
+    System.out.println("test4");
     for (int i = 0; i < 11000; i++) {
       java.util.Arrays.fill(arr, 0);
       test4(-1, -10, arr);
@@ -140,22 +150,25 @@
         break;
       }
     }
+    System.out.println("test5");
     for (int i = 0; i < 11000; i++) {
-      int k = test5(1);
-      if (k != 0) {
-        System.out.println("FAILED: " + k + " != 0");
+      int k = test5(limit6);
+      if (k != limit5*2) {
+        System.out.println("FAILED: " + k + " != " + limit5*2);
         failed = true;
         break;
       }
     }
+    System.out.println("test6");
     for (int i = 0; i < 11000; i++) {
-      int k = test6(-1);
-      if (k != 0) {
-        System.out.println("FAILED: " + k + " != 0");
+      int k = test6(limit5);
+      if (k != limit6*2) {
+        System.out.println("FAILED: " + k + " != " + limit6*2);
         failed = true;
         break;
       }
     }
+    System.out.println("finish");
     if (failed)
       System.exit(97);
   }